|  |  | | | Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » saving a paletted PNG Goto Forum:
	| 
		
			| saving a paletted PNG [message #6067] | Sun, 29 October 2006 20:42  |  
			| 
				
				
					|  lindquist Messages: 33
 Registered: March 2006
 Location: Denmark
 | Member |  |  |  
	| Hi folks. I have a problem with saving a paletted png image. From looking in plugin/png it seems that it is actually handling paletted images, but I always end up with a 24bit png. The problem seems to be PixelArrayToImage which converts my PixelArray (8bpp) to a Image.
 
 I have tried without success to create a Draw that will maintain the paletted format.
 
 Can anyone help me out here, I'm not sure if the support is there or if I need to do some hacking.
 
 Any clues/pointers would be very much appreciated.
 I need the exported png to be paletted!
 
 Thanx, Tomas
 |  
	|  |  |  
	| 
		
			| Re: saving a paletted PNG [message #6069 is a reply to message #6067] | Sun, 29 October 2006 20:53   |  
			| 
				
				
					|  lindquist Messages: 33
 Registered: March 2006
 Location: Denmark
 | Member |  |  |  
	| this is basically what I'm doing: (greatly simplified) 
 
 void writePNG(const String& filename)
{
	Vector<Color> pal;
	pal.Add(Color(0,0,0));
	
	PixelArray pix(100, 100, 8, 1, NULL, pal);
	
	for (int i=0; i<10000; ++i)
		pix.pixels[i] = 0;
	
	Image img = PixelArrayToImage(pix);
	PngEncoder::New()->SaveImageFile(filename, img);
}[Updated on: Sun, 29 October 2006 20:54] Report message to a moderator |  
	|  |  |  
	|  |  
	|  |  
	|  |  
	| 
		
			| Re: saving a paletted PNG [message #6077 is a reply to message #6076] | Mon, 30 October 2006 00:34   |  
			| 
				
				|  |  mirek Messages: 14271
 Registered: November 2005
 | Ultimate Member |  |  |  
	| | lindquist wrote on Sun, 29 October 2006 18:10 |  | I'm having some more problems.
 I have this test code:
 
 
 
void WritePNG(const String& filename)
{
	ImageBuffer ib(256, 256);
	ib.SetKind(IMAGE_OPAQUE);
	
	RGBA pal[256];
	for (int i=0; i<256; ++i)
	{
		pal[i] = Color(i,i,i);
	}
	
	int idx = 0;
	for (int y=0; y<256; ++y)
	{
		RGBA* line = ib[y];
		for (int x=0; x<256; ++x)
		{
			*line = pal[idx%256];
			++line;
			++idx;
		}
	}
	
	PNGEncoder png(8);
	png.SetPalette(pal);
	png.SaveFile(filename, ib);
}
 I would assume this code would generate a nice horizontal gradient, but it doesn't. Instead I get something that seems a bit like it's converted to 5bit colors. (every 8 pixels it jumps 16 indexes in the palette)
 
 | 
 
 That is unfortunately the limitation of palette conversion code - but in fact, we are not alone there... (almost any palette code I have studied before implementing U++ version did the same).
 
 The problem is - you have 256 colors in palette and you need to find nearest color for 256*256*256 colors for tens of thousands pixels. If you would perform search for each pixel, you would be exporting each Image for hours.
 
 Therefore you need something faster albeit less accurate. Usually, what you do is to cut some bits out and lookup index in map (you have to cut those bits because for full RGB you would need 16MB map). Works well except for single color gradients which is exactly the case you are trying....
 
 Mirek
 |  
	|  |  |  
	|  |  
	|  |  
	|  |  
	| 
		
			| Re: saving a paletted PNG [message #6088 is a reply to message #6080] | Mon, 30 October 2006 07:33   |  
			| 
				
				|  |  mirek Messages: 14271
 Registered: November 2005
 | Ultimate Member |  |  |  
	| OK, I see 3 possible solution: 
 * Quick fix, without altering U++, little bit ugly
 
 See PalleteCv class, Get. As you are able to set any palette to RasterEncoder, it is possible, based on PalleteCv conversion, to build special palette and
 
 RGBA PaletteIndex(int index);
 
 that will force those shifted values to produce specific index. Later I would add this to U++. Would be a bit slow, but not extremely slow.
 
 * Indexed mode in PaletteCv and/or RasterFormat
 
 Alter conversion routines to use some channel (most likely R
  as direct palette index. E.g. by using (PaletteCv *)1 in Write 
 * Perfect but complicated solution
 
 Well, this one already happened in Raster - add support for Raw modes in RasterEncoder (RasterEncoder::WriteLine(byte *data)). This is far the most work and paradigm shift too.
 
 Right now I would vote for the first option, in the same time I am afraid that last option would be nice to have too. But these are orthogonal.
 
 Mirek
 
 |  
	|  |  |  
	|  |  
	|  |  
	|  | 
 
 
 Current Time: Thu Oct 30 17:02:01 CET 2025 
 Total time taken to generate the page: 0.05170 seconds | 
 | 
 |