diff --git a/common/im_png.cpp b/common/im_png.cpp index b4c9369a..e6be0a89 100755 --- a/common/im_png.cpp +++ b/common/im_png.cpp @@ -15,361 +15,360 @@ // ============================================================================= -static void user_read_fn (png_structp png_ptr, png_bytep data, png_size_t length) +static void user_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { - png_size_t check; + png_size_t check; - // Read() returns 0 on error, so it is OK to store this in a png_size_t - // instead of an int, which is what Read() actually returns. - check = (png_size_t)((File*)png_ptr->io_ptr)->Read (data, length); + // Read() returns 0 on error, so it is OK to store this in a png_size_t + // instead of an int, which is what Read() actually returns. + check = (png_size_t)((File*)png_get_io_ptr(png_ptr))->Read(data, length); - if (check != length) - png_error(png_ptr, "Read Error"); + if (check != length) + png_error(png_ptr, "Read Error"); } -bool Image::LoadPNG (File& file) +bool Image::LoadPNG(File& file) { - unsigned char sig[8], red, green, blue; - unsigned char *image_data = NULL; - unsigned char *src, *dest; - unsigned char r, g, b, a; - unsigned long i, row; - unsigned long image_rowbytes; - png_color_16p pBackground; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - png_uint_32 width, height; - png_bytepp row_pointers = NULL; - int bit_depth, color_type; - int image_channels; - double gamma; + unsigned char sig[8], red, green, blue; + unsigned char *image_data = NULL; + unsigned char *src, *dest; + unsigned char r, g, b, a; + unsigned long i, row; + unsigned long image_rowbytes; + png_color_16p pBackground; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + png_bytepp row_pointers = NULL; + int bit_depth, color_type; + int image_channels; + double gamma; - FreeData (); + FreeData(); - file.Read (sig, 8); - if (!png_check_sig(sig, 8)) - return false; // bad signature + file.Read(sig, 8); + if (!png_check_sig(sig, 8)) + return false; // bad signature - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - return false; // out of memory - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - return false; // out of memory - } + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + return false; // out of memory - if (setjmp(png_ptr->jmpbuf)) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return false; - } + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; // out of memory + } - png_set_read_fn(png_ptr, (void *)&file, user_read_fn); -// png_init_io(png_ptr, f); - png_set_sig_bytes(png_ptr, 8); // we already read the 8 signature bytes + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return false; + } - png_read_info(png_ptr, info_ptr); // read all PNG info up to image data - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - NULL, NULL, NULL); + png_set_read_fn(png_ptr, (void*)&file, user_read_fn); + // png_init_io(png_ptr, f); + png_set_sig_bytes(png_ptr, 8); // we already read the 8 signature bytes - if (setjmp(png_ptr->jmpbuf)) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return false; - } + png_read_info(png_ptr, info_ptr); // read all PNG info up to image data + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) - { - png_get_bKGD(png_ptr, info_ptr, &pBackground); + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return false; + } - if (setjmp (png_ptr->jmpbuf)) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return false; - } + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) + { + png_get_bKGD(png_ptr, info_ptr, &pBackground); - // however, it always returns the raw bKGD data, regardless of any - // bit-depth transformations, so check depth and adjust if necessary - if (bit_depth == 16) - { - red = pBackground->red >> 8; - green = pBackground->green >> 8; - blue = pBackground->blue >> 8; - } - else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - { - if (bit_depth == 1) - red = green = blue = pBackground->gray? 255 : 0; - else if (bit_depth == 2) - red = green = blue = (255/3) * pBackground->gray; - else // bit_depth == 4 - red = green = blue = (255/15) * pBackground->gray; - } - else - { - red = (unsigned char)pBackground->red; - green = (unsigned char)pBackground->green; - blue = (unsigned char)pBackground->blue; - } - } - else - { - if (setjmp (png_ptr->jmpbuf)) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return false; - } + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return false; + } - red = green = blue = 0; - } + // however, it always returns the raw bKGD data, regardless of any + // bit-depth transformations, so check depth and adjust if necessary + if (bit_depth == 16) + { + red = pBackground->red >> 8; + green = pBackground->green >> 8; + blue = pBackground->blue >> 8; + } + else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + { + if (bit_depth == 1) + red = green = blue = pBackground->gray? 255 : 0; + else if (bit_depth == 2) + red = green = blue = (255/3) * pBackground->gray; + else // bit_depth == 4 + red = green = blue = (255/15) * pBackground->gray; + } + else + { + red = (unsigned char)pBackground->red; + green = (unsigned char)pBackground->green; + blue = (unsigned char)pBackground->blue; + } + } + else + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return false; + } - // expand palette images to RGB, low-bit-depth grayscale images to 8 bits, - // transparency chunks to full alpha channel; strip 16-bit-per-sample - // images to 8 bits per sample; and convert grayscale to RGB[A] - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - if (bit_depth == 16) - png_set_strip_16(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); + red = green = blue = 0; + } - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) - png_set_gamma(png_ptr, 2.2, gamma); + // expand palette images to RGB, low-bit-depth grayscale images to 8 bits, + // transparency chunks to full alpha channel; strip 16-bit-per-sample + // images to 8 bits per sample; and convert grayscale to RGB[A] + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (bit_depth == 16) + png_set_strip_16(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); - // all transformations have been registered; now update info_ptr data, - // get rowbytes and channels, and allocate image memory - png_read_update_info(png_ptr, info_ptr); + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, 2.2, gamma); - image_rowbytes = png_get_rowbytes(png_ptr, info_ptr); - image_channels = (int)png_get_channels(png_ptr, info_ptr); + // all transformations have been registered; now update info_ptr data, + // get rowbytes and channels, and allocate image memory + png_read_update_info(png_ptr, info_ptr); - if ((image_data = (unsigned char*)malloc(image_rowbytes*height)) == NULL) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return false; - } + image_rowbytes = png_get_rowbytes(png_ptr, info_ptr); + image_channels = (int)png_get_channels(png_ptr, info_ptr); - if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(image_data); - return false; - } + if ((image_data = (unsigned char*)malloc(image_rowbytes*height)) == NULL) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return false; + } - // set the individual row_pointers to point at the correct offsets - for (i = 0; i < height; ++i) - row_pointers[i] = image_data + i*image_rowbytes; + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + return false; + } - // now we can go ahead and just read the whole image - png_read_image(png_ptr, row_pointers); + // set the individual row_pointers to point at the correct offsets + for (i = 0; i < height; ++i) + row_pointers[i] = image_data + i*image_rowbytes; - // and we're done! (png_read_end() can be omitted if no processing of - // post-IDAT text/time/etc. is desired) - free(row_pointers); - row_pointers = NULL; + // now we can go ahead and just read the whole image + png_read_image(png_ptr, row_pointers); - png_read_end(png_ptr, NULL); + // and we're done! (png_read_end() can be omitted if no processing of + // post-IDAT text/time/etc. is desired) + free(row_pointers); + row_pointers = NULL; - // done with PNG file, so clean up to minimize memory usage - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + png_read_end(png_ptr, NULL); - if (!image_data) - return false; + // done with PNG file, so clean up to minimize memory usage + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - // get our buffer set to hold data - m_pData = (unsigned char*)malloc(width*height*image_channels); + if (!image_data) + return false; - if (m_pData == NULL) - { - free (image_data); - return false; - } + // get our buffer set to hold data + m_pData = (unsigned char*)malloc(width*height*image_channels); - m_nWidth = width; - m_nHeight = height; - if (image_channels == 3) - m_bAlpha = false; - else - m_bAlpha = true; + if (m_pData == NULL) + { + free (image_data); + return false; + } - for (row = 0; row < height; row++) - { - src = image_data + row*image_rowbytes; - dest = m_pData + row*image_channels*width; + m_nWidth = width; + m_nHeight = height; + if (image_channels == 3) + m_bAlpha = false; + else + m_bAlpha = true; - if (image_channels == 3) - { - for (i = width; i > 0; i--) - { - r = *src++; - g = *src++; - b = *src++; - *dest++ = r; - *dest++ = g; - *dest++ = b; - } - } - else // if (image_channels == 4) - { - for (i = width; i > 0; i--) - { - r = *src++; - g = *src++; - b = *src++; - a = *src++; + for (row = 0; row < height; row++) + { + src = image_data + row*image_rowbytes; + dest = m_pData + row*image_channels*width; - if (a == 255) - { - *dest++ = r; - *dest++ = g; - *dest++ = b; - } - else if (a == 0) - { - *dest++ = red; - *dest++ = green; - *dest++ = blue; - } - else - { - // this macro (copied from png.h) composites the - // foreground and background values and puts the - // result into the first argument; there are no - // side effects with the first argument - alpha_composite(*dest++, r, a, red); - alpha_composite(*dest++, g, a, green); - alpha_composite(*dest++, b, a, blue); - } - *dest++ = a; - } - } - } + if (image_channels == 3) + { + for (i = width; i > 0; i--) + { + r = *src++; + g = *src++; + b = *src++; + *dest++ = r; + *dest++ = g; + *dest++ = b; + } + } + else // if (image_channels == 4) + { + for (i = width; i > 0; i--) + { + r = *src++; + g = *src++; + b = *src++; + a = *src++; - free(image_data); - return true; + if (a == 255) + { + *dest++ = r; + *dest++ = g; + *dest++ = b; + } + else if (a == 0) + { + *dest++ = red; + *dest++ = green; + *dest++ = blue; + } + else + { + // this macro (copied from png.h) composites the + // foreground and background values and puts the + // result into the first argument; there are no + // side effects with the first argument + alpha_composite(*dest++, r, a, red); + alpha_composite(*dest++, g, a, green); + alpha_composite(*dest++, b, a, blue); + } + *dest++ = a; + } + } + } + + free(image_data); + return true; } // ============================================================================= -static void user_write_fn (png_structp png_ptr, png_bytep data, png_size_t length) +static void user_write_fn(png_structp png_ptr, png_bytep data, png_size_t length) { - png_uint_32 check; + png_uint_32 check; - check = ((File*)png_ptr->io_ptr)->Write (data, length); - if (check != length) - { - png_error(png_ptr, "Write Error"); - } + check = ((File*)png_get_io_ptr(png_ptr))->Write(data, length); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } } -static void user_flush_fn (png_structp png_ptr) +static void user_flush_fn(png_structp png_ptr) { - ((File*)png_ptr->io_ptr)->Flush (); + ((File*)png_get_io_ptr(png_ptr))->Flush(); } -bool Image::SavePNG (File& file, bool transparent, bool interlaced, unsigned char* background) const +bool Image::SavePNG(File& file, bool transparent, bool interlaced, unsigned char* background) const { - png_structp png_ptr; - png_infop info_ptr; - png_bytepp row_pointers = NULL; - png_color_8 sig_bit; - png_color_16 bg; - int i; + png_structp png_ptr; + png_infop info_ptr; + png_bytepp row_pointers = NULL; + png_color_8 sig_bit; + png_color_16 bg; + int i; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - return false; + png_ptr = png_create_write_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_write_struct(&png_ptr, NULL); - return false; - } + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, NULL); + return false; + } - if (setjmp(png_ptr->jmpbuf)) - { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return false; - } + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } -// png_init_io(png_ptr, fp); - png_set_write_fn (png_ptr, &file, user_write_fn, user_flush_fn); + // png_init_io(png_ptr, fp); + png_set_write_fn(png_ptr, &file, user_write_fn, user_flush_fn); - png_set_IHDR (png_ptr, info_ptr, m_nWidth, m_nHeight, 8, + png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, transparent ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - bg.red = background[0]; - bg.green = background[1]; - bg.blue = background[2]; - png_set_bKGD(png_ptr, info_ptr, &bg); + bg.red = background[0]; + bg.green = background[1]; + bg.blue = background[2]; + png_set_bKGD(png_ptr, info_ptr, &bg); - png_write_info(png_ptr, info_ptr); + png_write_info(png_ptr, info_ptr); - // Set the true bit depth of the image data - sig_bit.red = 8; - sig_bit.green = 8; - sig_bit.blue = 8; - sig_bit.alpha = 8; + // Set the true bit depth of the image data + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; - png_set_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_sBIT(png_ptr, info_ptr, &sig_bit); - if ((row_pointers = (png_bytepp)malloc(m_nHeight*sizeof(png_bytep))) == NULL) - { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return false; - } + if ((row_pointers = (png_bytepp)malloc(m_nHeight*sizeof(png_bytep))) == NULL) + { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } - // set the individual row_pointers to point at the correct offsets - if (transparent) - { - unsigned char *buf, *src, *dst, alpha; - dst = buf = (unsigned char*)malloc (m_nWidth*m_nHeight*4); - src = m_pData; + // set the individual row_pointers to point at the correct offsets + if (transparent) + { + unsigned char *buf, *src, *dst, alpha; + dst = buf = (unsigned char*)malloc(m_nWidth*m_nHeight*4); + src = m_pData; - for (i = 0; i < m_nWidth*m_nHeight; i++) - { - if ((src[0] == background[0]) && - (src[1] == background[1]) && - (src[2] == background[2])) - alpha = 0; - else - alpha = 255; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = alpha; - } + for (i = 0; i < m_nWidth*m_nHeight; i++) + { + if ((src[0] == background[0]) && + (src[1] == background[1]) && + (src[2] == background[2])) + alpha = 0; + else + alpha = 255; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = alpha; + } - for (i = 0; i < m_nHeight; i++) - row_pointers[i] = buf + i*m_nWidth*4; - png_write_image(png_ptr, row_pointers); + for (i = 0; i < m_nHeight; i++) + row_pointers[i] = buf + i*m_nWidth*4; + png_write_image(png_ptr, row_pointers); - free(buf); - } - else - { - for (i = 0; i < m_nHeight; i++) - row_pointers[i] = m_pData + i*m_nWidth*3; - png_write_image(png_ptr, row_pointers); - } + free(buf); + } + else + { + for (i = 0; i < m_nHeight; i++) + row_pointers[i] = m_pData + i*m_nWidth*3; + png_write_image(png_ptr, row_pointers); + } - free(row_pointers); + free(row_pointers); - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); - return true; + return true; } #endif // LC_HAVE_PNGLIB