mirror of
https://github.com/leozide/leocad
synced 2025-01-29 20:34:50 +01:00
Updated libpng to current version.
This commit is contained in:
parent
bd2a951314
commit
ca7007613d
1 changed files with 286 additions and 287 deletions
|
@ -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
|
// 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.
|
// instead of an int, which is what Read() actually returns.
|
||||||
check = (png_size_t)((File*)png_ptr->io_ptr)->Read (data, length);
|
check = (png_size_t)((File*)png_get_io_ptr(png_ptr))->Read(data, length);
|
||||||
|
|
||||||
if (check != length)
|
if (check != length)
|
||||||
png_error(png_ptr, "Read Error");
|
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 sig[8], red, green, blue;
|
||||||
unsigned char *image_data = NULL;
|
unsigned char *image_data = NULL;
|
||||||
unsigned char *src, *dest;
|
unsigned char *src, *dest;
|
||||||
unsigned char r, g, b, a;
|
unsigned char r, g, b, a;
|
||||||
unsigned long i, row;
|
unsigned long i, row;
|
||||||
unsigned long image_rowbytes;
|
unsigned long image_rowbytes;
|
||||||
png_color_16p pBackground;
|
png_color_16p pBackground;
|
||||||
png_structp png_ptr = NULL;
|
png_structp png_ptr = NULL;
|
||||||
png_infop info_ptr = NULL;
|
png_infop info_ptr = NULL;
|
||||||
png_uint_32 width, height;
|
png_uint_32 width, height;
|
||||||
png_bytepp row_pointers = NULL;
|
png_bytepp row_pointers = NULL;
|
||||||
int bit_depth, color_type;
|
int bit_depth, color_type;
|
||||||
int image_channels;
|
int image_channels;
|
||||||
double gamma;
|
double gamma;
|
||||||
|
|
||||||
FreeData ();
|
FreeData();
|
||||||
|
|
||||||
file.Read (sig, 8);
|
file.Read(sig, 8);
|
||||||
if (!png_check_sig(sig, 8))
|
if (!png_check_sig(sig, 8))
|
||||||
return false; // bad signature
|
return false; // bad signature
|
||||||
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
if (!png_ptr)
|
if (!png_ptr)
|
||||||
return false; // out of memory
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setjmp(png_ptr->jmpbuf))
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
{
|
if (!info_ptr)
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
{
|
||||||
return false;
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
}
|
return false; // out of memory
|
||||||
|
}
|
||||||
|
|
||||||
png_set_read_fn(png_ptr, (void *)&file, user_read_fn);
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
// png_init_io(png_ptr, f);
|
{
|
||||||
png_set_sig_bytes(png_ptr, 8); // we already read the 8 signature bytes
|
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_set_read_fn(png_ptr, (void*)&file, user_read_fn);
|
||||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
|
// png_init_io(png_ptr, f);
|
||||||
NULL, NULL, NULL);
|
png_set_sig_bytes(png_ptr, 8); // we already read the 8 signature bytes
|
||||||
|
|
||||||
if (setjmp(png_ptr->jmpbuf))
|
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_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
{
|
{
|
||||||
png_get_bKGD(png_ptr, info_ptr, &pBackground);
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (setjmp (png_ptr->jmpbuf))
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
|
||||||
{
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
png_get_bKGD(png_ptr, info_ptr, &pBackground);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// however, it always returns the raw bKGD data, regardless of any
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
// bit-depth transformations, so check depth and adjust if necessary
|
{
|
||||||
if (bit_depth == 16)
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
{
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
red = green = blue = 0;
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
// expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
|
||||||
png_set_gamma(png_ptr, 2.2, gamma);
|
// 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,
|
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
||||||
// get rowbytes and channels, and allocate image memory
|
png_set_gamma(png_ptr, 2.2, gamma);
|
||||||
png_read_update_info(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
image_rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
// all transformations have been registered; now update info_ptr data,
|
||||||
image_channels = (int)png_get_channels(png_ptr, info_ptr);
|
// 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)
|
image_rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
{
|
image_channels = (int)png_get_channels(png_ptr, info_ptr);
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL)
|
if ((image_data = (unsigned char*)malloc(image_rowbytes*height)) == NULL)
|
||||||
{
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
free(image_data);
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set the individual row_pointers to point at the correct offsets
|
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL)
|
||||||
for (i = 0; i < height; ++i)
|
{
|
||||||
row_pointers[i] = image_data + i*image_rowbytes;
|
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
|
// set the individual row_pointers to point at the correct offsets
|
||||||
png_read_image(png_ptr, row_pointers);
|
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
|
// now we can go ahead and just read the whole image
|
||||||
// post-IDAT text/time/etc. is desired)
|
png_read_image(png_ptr, row_pointers);
|
||||||
free(row_pointers);
|
|
||||||
row_pointers = NULL;
|
|
||||||
|
|
||||||
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_read_end(png_ptr, NULL);
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
|
|
||||||
if (!image_data)
|
// done with PNG file, so clean up to minimize memory usage
|
||||||
return false;
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
||||||
// get our buffer set to hold data
|
if (!image_data)
|
||||||
m_pData = (unsigned char*)malloc(width*height*image_channels);
|
return false;
|
||||||
|
|
||||||
if (m_pData == NULL)
|
// get our buffer set to hold data
|
||||||
{
|
m_pData = (unsigned char*)malloc(width*height*image_channels);
|
||||||
free (image_data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_nWidth = width;
|
if (m_pData == NULL)
|
||||||
m_nHeight = height;
|
{
|
||||||
if (image_channels == 3)
|
free (image_data);
|
||||||
m_bAlpha = false;
|
return false;
|
||||||
else
|
}
|
||||||
m_bAlpha = true;
|
|
||||||
|
|
||||||
for (row = 0; row < height; row++)
|
m_nWidth = width;
|
||||||
{
|
m_nHeight = height;
|
||||||
src = image_data + row*image_rowbytes;
|
if (image_channels == 3)
|
||||||
dest = m_pData + row*image_channels*width;
|
m_bAlpha = false;
|
||||||
|
else
|
||||||
|
m_bAlpha = true;
|
||||||
|
|
||||||
if (image_channels == 3)
|
for (row = 0; row < height; row++)
|
||||||
{
|
{
|
||||||
for (i = width; i > 0; i--)
|
src = image_data + row*image_rowbytes;
|
||||||
{
|
dest = m_pData + row*image_channels*width;
|
||||||
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++;
|
|
||||||
|
|
||||||
if (a == 255)
|
if (image_channels == 3)
|
||||||
{
|
{
|
||||||
*dest++ = r;
|
for (i = width; i > 0; i--)
|
||||||
*dest++ = g;
|
{
|
||||||
*dest++ = b;
|
r = *src++;
|
||||||
}
|
g = *src++;
|
||||||
else if (a == 0)
|
b = *src++;
|
||||||
{
|
*dest++ = r;
|
||||||
*dest++ = red;
|
*dest++ = g;
|
||||||
*dest++ = green;
|
*dest++ = b;
|
||||||
*dest++ = blue;
|
}
|
||||||
}
|
}
|
||||||
else
|
else // if (image_channels == 4)
|
||||||
{
|
{
|
||||||
// this macro (copied from png.h) composites the
|
for (i = width; i > 0; i--)
|
||||||
// foreground and background values and puts the
|
{
|
||||||
// result into the first argument; there are no
|
r = *src++;
|
||||||
// side effects with the first argument
|
g = *src++;
|
||||||
alpha_composite(*dest++, r, a, red);
|
b = *src++;
|
||||||
alpha_composite(*dest++, g, a, green);
|
a = *src++;
|
||||||
alpha_composite(*dest++, b, a, blue);
|
|
||||||
}
|
|
||||||
*dest++ = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(image_data);
|
if (a == 255)
|
||||||
return true;
|
{
|
||||||
|
*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);
|
check = ((File*)png_get_io_ptr(png_ptr))->Write(data, length);
|
||||||
if (check != length)
|
if (check != length)
|
||||||
{
|
{
|
||||||
png_error(png_ptr, "Write Error");
|
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_structp png_ptr;
|
||||||
png_infop info_ptr;
|
png_infop info_ptr;
|
||||||
png_bytepp row_pointers = NULL;
|
png_bytepp row_pointers = NULL;
|
||||||
png_color_8 sig_bit;
|
png_color_8 sig_bit;
|
||||||
png_color_16 bg;
|
png_color_16 bg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
if (!png_ptr)
|
if (!png_ptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (!info_ptr)
|
if (!info_ptr)
|
||||||
{
|
{
|
||||||
png_destroy_write_struct(&png_ptr, NULL);
|
png_destroy_write_struct(&png_ptr, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setjmp(png_ptr->jmpbuf))
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
{
|
{
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// png_init_io(png_ptr, fp);
|
// png_init_io(png_ptr, fp);
|
||||||
png_set_write_fn (png_ptr, &file, user_write_fn, user_flush_fn);
|
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,
|
transparent ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
|
||||||
interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
|
interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
|
||||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
bg.red = background[0];
|
bg.red = background[0];
|
||||||
bg.green = background[1];
|
bg.green = background[1];
|
||||||
bg.blue = background[2];
|
bg.blue = background[2];
|
||||||
png_set_bKGD(png_ptr, info_ptr, &bg);
|
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
|
// Set the true bit depth of the image data
|
||||||
sig_bit.red = 8;
|
sig_bit.red = 8;
|
||||||
sig_bit.green = 8;
|
sig_bit.green = 8;
|
||||||
sig_bit.blue = 8;
|
sig_bit.blue = 8;
|
||||||
sig_bit.alpha = 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)
|
if ((row_pointers = (png_bytepp)malloc(m_nHeight*sizeof(png_bytep))) == NULL)
|
||||||
{
|
{
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the individual row_pointers to point at the correct offsets
|
// set the individual row_pointers to point at the correct offsets
|
||||||
if (transparent)
|
if (transparent)
|
||||||
{
|
{
|
||||||
unsigned char *buf, *src, *dst, alpha;
|
unsigned char *buf, *src, *dst, alpha;
|
||||||
dst = buf = (unsigned char*)malloc (m_nWidth*m_nHeight*4);
|
dst = buf = (unsigned char*)malloc(m_nWidth*m_nHeight*4);
|
||||||
src = m_pData;
|
src = m_pData;
|
||||||
|
|
||||||
for (i = 0; i < m_nWidth*m_nHeight; i++)
|
for (i = 0; i < m_nWidth*m_nHeight; i++)
|
||||||
{
|
{
|
||||||
if ((src[0] == background[0]) &&
|
if ((src[0] == background[0]) &&
|
||||||
(src[1] == background[1]) &&
|
(src[1] == background[1]) &&
|
||||||
(src[2] == background[2]))
|
(src[2] == background[2]))
|
||||||
alpha = 0;
|
alpha = 0;
|
||||||
else
|
else
|
||||||
alpha = 255;
|
alpha = 255;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = alpha;
|
*dst++ = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < m_nHeight; i++)
|
for (i = 0; i < m_nHeight; i++)
|
||||||
row_pointers[i] = buf + i*m_nWidth*4;
|
row_pointers[i] = buf + i*m_nWidth*4;
|
||||||
png_write_image(png_ptr, row_pointers);
|
png_write_image(png_ptr, row_pointers);
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; i < m_nHeight; i++)
|
for (i = 0; i < m_nHeight; i++)
|
||||||
row_pointers[i] = m_pData + i*m_nWidth*3;
|
row_pointers[i] = m_pData + i*m_nWidth*3;
|
||||||
png_write_image(png_ptr, row_pointers);
|
png_write_image(png_ptr, row_pointers);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(row_pointers);
|
free(row_pointers);
|
||||||
|
|
||||||
png_write_end(png_ptr, info_ptr);
|
png_write_end(png_ptr, info_ptr);
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // LC_HAVE_PNGLIB
|
#endif // LC_HAVE_PNGLIB
|
||||||
|
|
Loading…
Add table
Reference in a new issue