X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b61cc19c06d9795c73fc6fbe893e92898938c70e..7ddb15416407390de67cc26b04e91ea99a521f57:/src/png/pngwtran.c diff --git a/src/png/pngwtran.c b/src/png/pngwtran.c index 070caa544d..96608efcb4 100644 --- a/src/png/pngwtran.c +++ b/src/png/pngwtran.c @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.4.1 [February 25, 2010] - * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * Last changed in libpng 1.5.6 [November 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -11,16 +11,16 @@ * and license in png.h */ -#define PNG_NO_PEDANTIC_WARNINGS -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED #include "pngpriv.h" +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Transform the data according to the user's wishes. The order of * transformations is significant. */ void /* PRIVATE */ -png_do_write_transformations(png_structp png_ptr) +png_do_write_transformations(png_structp png_ptr, png_row_infop row_info) { png_debug(1, "in png_do_write_transformations"); @@ -30,56 +30,65 @@ png_do_write_transformations(png_structp png_ptr) #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED if (png_ptr->transformations & PNG_USER_TRANSFORM) if (png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* User write transform + (*(png_ptr->write_user_transform_fn)) /* User write transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ + (png_ptr, /* png_ptr */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ #endif + #ifdef PNG_WRITE_FILLER_SUPPORTED if (png_ptr->transformations & PNG_FILLER) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->flags); + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); #endif + #ifdef PNG_WRITE_PACKSWAP_SUPPORTED if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_packswap(row_info, png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_PACK_SUPPORTED if (png_ptr->transformations & PNG_PACK) - png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->bit_depth); + png_do_pack(row_info, png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); #endif + #ifdef PNG_WRITE_SWAP_SUPPORTED if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_swap(row_info, png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_SHIFT_SUPPORTED if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); + png_do_shift(row_info, png_ptr->row_buf + 1, + &(png_ptr->shift)); #endif + #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_BGR_SUPPORTED if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_bgr(row_info, png_ptr->row_buf + 1); #endif + #ifdef PNG_WRITE_INVERT_SUPPORTED if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_invert(row_info, png_ptr->row_buf + 1); #endif } @@ -114,9 +123,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) { if (*sp != 0) v |= mask; + sp++; + if (mask > 1) mask >>= 1; + else { mask = 0x80; @@ -125,10 +137,13 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) v = 0; } } + if (mask != 0x80) *dp = (png_byte)v; + break; } + case 2: { png_bytep sp, dp; @@ -140,12 +155,14 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp = row; shift = 6; v = 0; + for (i = 0; i < row_width; i++) { png_byte value; value = (png_byte)(*sp & 0x03); v |= (value << shift); + if (shift == 0) { shift = 6; @@ -153,14 +170,19 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp++; v = 0; } + else shift -= 2; + sp++; } + if (shift != 6) *dp = (png_byte)v; + break; } + case 4: { png_bytep sp, dp; @@ -172,6 +194,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp = row; shift = 4; v = 0; + for (i = 0; i < row_width; i++) { png_byte value; @@ -186,20 +209,27 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) dp++; v = 0; } + else shift -= 4; sp++; } + if (shift != 4) *dp = (png_byte)v; + break; } + + default: + break; } + row_info->bit_depth = (png_byte)bit_depth; row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); + row_info->width); } } #endif @@ -213,12 +243,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) * data to 0 to 15. */ void /* PRIVATE */ -png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) { png_debug(1, "in png_do_shift"); - if ( - row_info->color_type != PNG_COLOR_TYPE_PALETTE) + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) { int shift_start[4], shift_dec[4]; int channels = 0; @@ -228,19 +258,23 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) shift_start[channels] = row_info->bit_depth - bit_depth->red; shift_dec[channels] = bit_depth->red; channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; shift_dec[channels] = bit_depth->green; channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; shift_dec[channels] = bit_depth->blue; channels++; } + else { shift_start[channels] = row_info->bit_depth - bit_depth->gray; shift_dec[channels] = bit_depth->gray; channels++; } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) { shift_start[channels] = row_info->bit_depth - bit_depth->alpha; @@ -252,14 +286,16 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) if (row_info->bit_depth < 8) { png_bytep bp = row; - png_uint_32 i; + png_size_t i; png_byte mask; - png_uint_32 row_bytes = row_info->rowbytes; + png_size_t row_bytes = row_info->rowbytes; if (bit_depth->gray == 1 && row_info->bit_depth == 2) mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) mask = 0x11; + else mask = 0xff; @@ -270,15 +306,18 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = *bp; *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) { if (j > 0) *bp |= (png_byte)((v << j) & 0xff); + else *bp |= (png_byte)((v >> (-j)) & mask); } } } + else if (row_info->bit_depth == 8) { png_bytep bp = row; @@ -294,15 +333,18 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = *bp; *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) { if (j > 0) *bp |= (png_byte)((v << j) & 0xff); + else *bp |= (png_byte)((v >> (-j)) & 0xff); } } } + else { png_bytep bp; @@ -317,10 +359,12 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) { if (j > 0) value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); } @@ -341,12 +385,13 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) { if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - /* This converts from ARGB to RGBA */ if (row_info->bit_depth == 8) { + /* This converts from ARGB to RGBA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) { png_byte save = *(sp++); @@ -356,9 +401,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save; } } - /* This converts from AARRGGBB to RRGGBBAA */ + +#ifdef PNG_WRITE_16BIT_SUPPORTED else { + /* This converts from AARRGGBB to RRGGBBAA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -378,12 +425,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save[1]; } } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - /* This converts from AG to GA */ if (row_info->bit_depth == 8) { + /* This converts from AG to GA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -395,9 +444,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save; } } - /* This converts from AAGG to GGAA */ + +#ifdef PNG_WRITE_16BIT_SUPPORTED else { + /* This converts from AAGG to GGAA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -413,6 +464,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) *(dp++) = save[1]; } } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ } } } @@ -427,12 +479,13 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) { if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - /* This inverts the alpha channel in RGBA */ if (row_info->bit_depth == 8) { + /* This inverts the alpha channel in RGBA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) { /* Does nothing @@ -444,9 +497,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } - /* This inverts the alpha channel in RRGGBBAA */ + +#ifdef PNG_WRITE_16BIT_SUPPORTED else { + /* This inverts the alpha channel in RRGGBBAA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -466,12 +521,14 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - /* This inverts the alpha channel in GA */ if (row_info->bit_depth == 8) { + /* This inverts the alpha channel in GA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -482,9 +539,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } - /* This inverts the alpha channel in GGAA */ + +#ifdef PNG_WRITE_16BIT_SUPPORTED else { + /* This inverts the alpha channel in GGAA */ png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -500,10 +559,12 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = (png_byte)(255 - *(sp++)); } } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ } } } #endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED /* Undoes intrapixel differencing */ @@ -512,8 +573,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_write_intrapixel"); - if ( - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) { int bytes_per_pixel; png_uint_32 row_width = row_info->width; @@ -524,17 +584,21 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_RGB) bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) bytes_per_pixel = 4; + else return; for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - *(rp) = (png_byte)((*rp - *(rp+1))&0xff); - *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); } } + +#ifdef PNG_WRITE_16BIT_SUPPORTED else if (row_info->bit_depth == 16) { png_bytep rp; @@ -542,24 +606,27 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_RGB) bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) bytes_per_pixel = 8; + else return; for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); } } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ } } #endif /* PNG_MNG_FEATURES_SUPPORTED */