-
-bool wxPNGHandler::LoadFile( wxImage *image, const wxString& name )
-{
- FILE *f;
- png_structp png_ptr;
- png_infop info_ptr;
- unsigned char *ptr, **lines, *ptr2;
- int transp,bit_depth,color_type,interlace_type;
- png_uint_32 width, height;
- unsigned int i;
-
- image->Destroy();
-
- transp = 0;
- png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
- if (!png_ptr) return FALSE;
-
- info_ptr = png_create_info_struct( png_ptr );
- if (!info_ptr)
- {
- png_destroy_read_struct( &png_ptr, NULL, NULL );
- return FALSE;
- }
-
- if (setjmp(png_ptr->jmpbuf))
- {
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- return FALSE;
- }
-
- if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- {
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- return FALSE;
- }
-
- f = fopen( name, "rb" );
- png_init_io( png_ptr, f );
-
- png_read_info( png_ptr, info_ptr );
- png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL );
-
- if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
-
- png_set_strip_16( png_ptr );
- png_set_packing( png_ptr );
- if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr );
- png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
-
- image->Create( width, height );
-
- if (!image->Ok())
- {
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- return FALSE;
- }
-
- lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
- if (lines == NULL)
- {
- image->Destroy();
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- return FALSE;
- }
-
- for (i = 0; i < height; i++)
- {
- if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
- {
- image->Destroy();
- for (unsigned int n = 0; n < i; n++) free( lines[n] );
- free( lines );
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- return FALSE;
+
+ image->Destroy();
+
+ done = 0;
+ /*
+ * Reading the bmp header
+ */
+
+ stream.Read(&bbuf, 2);
+
+ stream.Read(dbuf, 4 * 4);
+
+ size = dbuf[0];
+ offset = dbuf[2];
+
+ stream.Read(dbuf, 4 * 2);
+ int width = (int)dbuf[0];
+ int height = (int)dbuf[1];
+ if (width > 32767)
+ {
+ wxLogError( _T("Image width > 32767 pixels for file\n") );
+ return FALSE;
+ }
+ if (height > 32767)
+ {
+ wxLogError( _T("Image height > 32767 pixels for file\n") );
+ return FALSE;
+ }
+ stream.Read(&word, 2);
+ planes = (int)word;
+ stream.Read(&word, 2);
+ bpp = (int)word;
+ if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
+ {
+ wxLogError( _T("unknown bitdepth in file\n") );
+ return FALSE;
+ }
+ stream.Read(dbuf, 4 * 4);
+ comp = (int)dbuf[0];
+ if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
+ {
+ wxLogError( _T("unknown encoding in Windows BMP file\n") );
+ return FALSE;
+ }
+ stream.Read(dbuf, 4 * 2);
+ ncolors = (int)dbuf[0];
+ if (ncolors == 0)
+ ncolors = 1 << bpp;
+ /* some more sanity checks */
+ if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
+ {
+ wxLogError( _T("encoding of BMP doesn't match bitdepth\n") );
+ return FALSE;
+ }
+ if (bpp < 16)
+ {
+ cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
+
+ if (!cmap)
+ {
+ wxLogError( _T("Cannot allocate RAM for color map in BMP file\n") );
+ return FALSE;
+ }
+ }
+ else
+ cmap = NULL;
+
+ image->Create( width, height );
+ ptr = image->GetData();
+ if (!ptr)
+ {
+ wxLogError( _T("Cannot allocate RAM for RGB data in file\n") );
+ if (cmap)
+ free(cmap);
+ return FALSE;
+ }
+
+ /*
+ * Reading the palette, if it exists.
+ */
+ if (bpp < 16 && ncolors != 0)
+ {
+ for (i = 0; i < ncolors; i++)
+ {
+ stream.Read(bbuf, 4);
+ cmap[i].b = bbuf[0];
+ cmap[i].g = bbuf[1];
+ cmap[i].r = bbuf[2];
+ }
+ }
+ else if (bpp == 16 || bpp == 32)
+ {
+ if (comp == BI_BITFIELDS)
+ {
+ int bit = 0;
+
+ stream.Read(dbuf, 4 * 3);
+ bmask = dbuf[0];
+ gmask = dbuf[1];
+ rmask = dbuf[2];
+ /* find shift amount.. ugly, but i can't think of a better way */
+ for (bit = 0; bit < bpp; bit++)
+ {
+ if (bmask & (1 << bit))
+ bshift = bit;
+ if (gmask & (1 << bit))
+ gshift = bit;
+ if (rmask & (1 << bit))
+ rshift = bit;
+ }
+ }
+ else if (bpp == 16)
+ {
+ rmask = 0x7C00;
+ gmask = 0x03E0;
+ bmask = 0x001F;
+ rshift = 10;
+ gshift = 5;
+ bshift = 0;
+ }
+ else if (bpp == 32)
+ {
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ rshift = 16;
+ gshift = 8;
+ bshift = 0;
+ }
+ }
+
+ /*
+ * Reading the image data
+ */
+ stream.SeekI(start_offset + offset);
+ data = ptr;
+
+ /* set the whole image to the background color */
+ if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
+ {
+ for (i = 0; i < width * height; i++)
+ {
+ *ptr++ = cmap[0].r;
+ *ptr++ = cmap[0].g;
+ *ptr++ = cmap[0].b;
+ }
+ ptr = data;
+ }
+ line = 0;
+ column = 0;
+#define poffset (line * width * 3 + column * 3)
+
+ /*
+ * BMPs are stored upside down... hmmmmmmmmmm....
+ */
+
+ linesize = ((width * bpp + 31) / 32) * 4;
+ for (line = (height - 1); line >= 0; line--)
+ {
+ linepos = 0;
+ for (column = 0; column < width;)
+ {
+ if (bpp < 16)
+ {
+ int index;
+
+ linepos++;
+ aByte = stream.GetC();
+ if (bpp == 1)
+ {
+ int bit = 0;
+
+ for (bit = 0; bit < 8; bit++)
+ {
+ index = ((aByte & (0x80 >> bit)) ? 1 : 0);
+ ptr[poffset] = cmap[index].r;
+ ptr[poffset + 1] = cmap[index].g;
+ ptr[poffset + 2] = cmap[index].b;
+ column++;
+ }
+ }
+ else if (bpp == 4)
+ {
+ if (comp == BI_RLE4)
+ {
+ wxLogError( _T("can't deal with 4bit encoded yet.\n") );
+ image->Destroy();
+ free(cmap);
+ return FALSE;
+ }
+ else
+ {
+ int nibble = 0;
+
+ for (nibble = 0; nibble < 2; nibble++)
+ {
+ index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
+ if (index >= 16)
+ index = 15;
+ ptr[poffset] = cmap[index].r;
+ ptr[poffset + 1] = cmap[index].g;
+ ptr[poffset + 2] = cmap[index].b;
+ column++;
+ }
+ }
+ }
+ else if (bpp == 8)
+ {
+ if (comp == BI_RLE8)
+ {
+ unsigned char first;
+
+ first = aByte;
+ aByte = stream.GetC();
+ if (first == 0)
+ {
+ if (aByte == 0)
+ {
+ /* column = width; */
+ }
+ else if (aByte == 1)
+ {
+ column = width;
+ line = -1;
+ }
+ else if (aByte == 2)
+ {
+ aByte = stream.GetC();
+ column += aByte;
+ linepos = column * bpp / 8;
+ aByte = stream.GetC();
+ line += aByte;
+ }
+ else
+ {
+ int absolute = aByte;
+
+ for (i = 0; i < absolute; i++)
+ {
+ linepos++;
+ aByte = stream.GetC();
+ ptr[poffset] = cmap[aByte].r;
+ ptr[poffset + 1] = cmap[aByte].g;
+ ptr[poffset + 2] = cmap[aByte].b;
+ column++;
+ }
+ if (absolute & 0x01)
+ aByte = stream.GetC();
+ }
+ }
+ else
+ {
+ for (i = 0; i < first; i++)
+ {
+ ptr[poffset] = cmap[aByte].r;
+ ptr[poffset + 1] = cmap[aByte].g;
+ ptr[poffset + 2] = cmap[aByte].b;
+ column++;
+ linepos++;
+ }
+ }
+ }
+ else
+ {
+ ptr[poffset] = cmap[aByte].r;
+ ptr[poffset + 1] = cmap[aByte].g;
+ ptr[poffset + 2] = cmap[aByte].b;
+ column++;
+ linepos += size;
+ }
+ }
+ }
+ else if (bpp == 24)
+ {
+ stream.Read(&bbuf, 3);
+ linepos += 3;
+ ptr[poffset] = (unsigned char)bbuf[2];
+ ptr[poffset + 1] = (unsigned char)bbuf[1];
+ ptr[poffset + 2] = (unsigned char)bbuf[0];
+ column++;
+ }
+ else if (bpp == 16)
+ {
+ unsigned char temp;
+
+ stream.Read(&word, 2);
+ linepos += 2;
+ temp = (word & rmask) >> rshift;
+ ptr[poffset] = temp;
+ temp = (word & gmask) >> gshift;
+ ptr[poffset + 1] = temp;
+ temp = (word & bmask) >> gshift;
+ ptr[poffset + 2] = temp;
+ column++;
+ }
+ else
+ {
+ unsigned char temp;
+
+ stream.Read(&dword, 4);
+ linepos += 4;
+ temp = (dword & rmask) >> rshift;
+ ptr[poffset] = temp;
+ temp = (dword & gmask) >> gshift;
+ ptr[poffset + 1] = temp;
+ temp = (dword & bmask) >> bshift;
+ ptr[poffset + 2] = temp;
+ column++;
+ }
+ }
+ while ((linepos < linesize) && (comp != 1) && (comp != 2))
+ {
+ stream.Read(&aByte, 1);
+ linepos += 1;
+ if (stream.LastError() != wxStream_NOERROR)
+ break;
+ }