1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libpng/pngrtran.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4991 @@ 1.4 + 1.5 +/* pngrtran.c - transforms the data in a row for PNG readers 1.6 + * 1.7 + * Last changed in libpng 1.6.10 [March 6, 2014] 1.8 + * Copyright (c) 1998-2014 Glenn Randers-Pehrson 1.9 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 1.10 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 1.11 + * 1.12 + * This code is released under the libpng license. 1.13 + * For conditions of distribution and use, see the disclaimer 1.14 + * and license in png.h 1.15 + * 1.16 + * This file contains functions optionally called by an application 1.17 + * in order to tell libpng how to handle data when reading a PNG. 1.18 + * Transformations that are used in both reading and writing are 1.19 + * in pngtrans.c. 1.20 + */ 1.21 + 1.22 +#include "pngpriv.h" 1.23 + 1.24 +#ifdef PNG_READ_SUPPORTED 1.25 + 1.26 +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ 1.27 +void PNGAPI 1.28 +png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) 1.29 +{ 1.30 + png_debug(1, "in png_set_crc_action"); 1.31 + 1.32 + if (png_ptr == NULL) 1.33 + return; 1.34 + 1.35 + /* Tell libpng how we react to CRC errors in critical chunks */ 1.36 + switch (crit_action) 1.37 + { 1.38 + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 1.39 + break; 1.40 + 1.41 + case PNG_CRC_WARN_USE: /* Warn/use data */ 1.42 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.43 + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 1.44 + break; 1.45 + 1.46 + case PNG_CRC_QUIET_USE: /* Quiet/use data */ 1.47 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.48 + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 1.49 + PNG_FLAG_CRC_CRITICAL_IGNORE; 1.50 + break; 1.51 + 1.52 + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ 1.53 + png_warning(png_ptr, 1.54 + "Can't discard critical data on CRC error"); 1.55 + case PNG_CRC_ERROR_QUIT: /* Error/quit */ 1.56 + 1.57 + case PNG_CRC_DEFAULT: 1.58 + default: 1.59 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.60 + break; 1.61 + } 1.62 + 1.63 + /* Tell libpng how we react to CRC errors in ancillary chunks */ 1.64 + switch (ancil_action) 1.65 + { 1.66 + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 1.67 + break; 1.68 + 1.69 + case PNG_CRC_WARN_USE: /* Warn/use data */ 1.70 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.71 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 1.72 + break; 1.73 + 1.74 + case PNG_CRC_QUIET_USE: /* Quiet/use data */ 1.75 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.76 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 1.77 + PNG_FLAG_CRC_ANCILLARY_NOWARN; 1.78 + break; 1.79 + 1.80 + case PNG_CRC_ERROR_QUIT: /* Error/quit */ 1.81 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.82 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 1.83 + break; 1.84 + 1.85 + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ 1.86 + 1.87 + case PNG_CRC_DEFAULT: 1.88 + default: 1.89 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.90 + break; 1.91 + } 1.92 +} 1.93 + 1.94 +#ifdef PNG_READ_TRANSFORMS_SUPPORTED 1.95 +/* Is it OK to set a transformation now? Only if png_start_read_image or 1.96 + * png_read_update_info have not been called. It is not necessary for the IHDR 1.97 + * to have been read in all cases, the parameter allows for this check too. 1.98 + */ 1.99 +static int 1.100 +png_rtran_ok(png_structrp png_ptr, int need_IHDR) 1.101 +{ 1.102 + if (png_ptr != NULL) 1.103 + { 1.104 + if (png_ptr->flags & PNG_FLAG_ROW_INIT) 1.105 + png_app_error(png_ptr, 1.106 + "invalid after png_start_read_image or png_read_update_info"); 1.107 + 1.108 + else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) 1.109 + png_app_error(png_ptr, "invalid before the PNG header has been read"); 1.110 + 1.111 + else 1.112 + { 1.113 + /* Turn on failure to initialize correctly for all transforms. */ 1.114 + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; 1.115 + 1.116 + return 1; /* Ok */ 1.117 + } 1.118 + } 1.119 + 1.120 + return 0; /* no png_error possible! */ 1.121 +} 1.122 +#endif 1.123 + 1.124 +#ifdef PNG_READ_BACKGROUND_SUPPORTED 1.125 +/* Handle alpha and tRNS via a background color */ 1.126 +void PNGFAPI 1.127 +png_set_background_fixed(png_structrp png_ptr, 1.128 + png_const_color_16p background_color, int background_gamma_code, 1.129 + int need_expand, png_fixed_point background_gamma) 1.130 +{ 1.131 + png_debug(1, "in png_set_background_fixed"); 1.132 + 1.133 + if (!png_rtran_ok(png_ptr, 0) || background_color == NULL) 1.134 + return; 1.135 + 1.136 + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 1.137 + { 1.138 + png_warning(png_ptr, "Application must supply a known background gamma"); 1.139 + return; 1.140 + } 1.141 + 1.142 + png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; 1.143 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.144 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.145 + 1.146 + png_ptr->background = *background_color; 1.147 + png_ptr->background_gamma = background_gamma; 1.148 + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 1.149 + if (need_expand) 1.150 + png_ptr->transformations |= PNG_BACKGROUND_EXPAND; 1.151 + else 1.152 + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 1.153 +} 1.154 + 1.155 +# ifdef PNG_FLOATING_POINT_SUPPORTED 1.156 +void PNGAPI 1.157 +png_set_background(png_structrp png_ptr, 1.158 + png_const_color_16p background_color, int background_gamma_code, 1.159 + int need_expand, double background_gamma) 1.160 +{ 1.161 + png_set_background_fixed(png_ptr, background_color, background_gamma_code, 1.162 + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); 1.163 +} 1.164 +# endif /* FLOATING_POINT */ 1.165 +#endif /* READ_BACKGROUND */ 1.166 + 1.167 +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the 1.168 + * one that pngrtran does first (scale) happens. This is necessary to allow the 1.169 + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. 1.170 + */ 1.171 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1.172 +void PNGAPI 1.173 +png_set_scale_16(png_structrp png_ptr) 1.174 +{ 1.175 + png_debug(1, "in png_set_scale_16"); 1.176 + 1.177 + if (!png_rtran_ok(png_ptr, 0)) 1.178 + return; 1.179 + 1.180 + png_ptr->transformations |= PNG_SCALE_16_TO_8; 1.181 +} 1.182 +#endif 1.183 + 1.184 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1.185 +/* Chop 16-bit depth files to 8-bit depth */ 1.186 +void PNGAPI 1.187 +png_set_strip_16(png_structrp png_ptr) 1.188 +{ 1.189 + png_debug(1, "in png_set_strip_16"); 1.190 + 1.191 + if (!png_rtran_ok(png_ptr, 0)) 1.192 + return; 1.193 + 1.194 + png_ptr->transformations |= PNG_16_TO_8; 1.195 +} 1.196 +#endif 1.197 + 1.198 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1.199 +void PNGAPI 1.200 +png_set_strip_alpha(png_structrp png_ptr) 1.201 +{ 1.202 + png_debug(1, "in png_set_strip_alpha"); 1.203 + 1.204 + if (!png_rtran_ok(png_ptr, 0)) 1.205 + return; 1.206 + 1.207 + png_ptr->transformations |= PNG_STRIP_ALPHA; 1.208 +} 1.209 +#endif 1.210 + 1.211 +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) 1.212 +static png_fixed_point 1.213 +translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, 1.214 + int is_screen) 1.215 +{ 1.216 + /* Check for flag values. The main reason for having the old Mac value as a 1.217 + * flag is that it is pretty near impossible to work out what the correct 1.218 + * value is from Apple documentation - a working Mac system is needed to 1.219 + * discover the value! 1.220 + */ 1.221 + if (output_gamma == PNG_DEFAULT_sRGB || 1.222 + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) 1.223 + { 1.224 + /* If there is no sRGB support this just sets the gamma to the standard 1.225 + * sRGB value. (This is a side effect of using this function!) 1.226 + */ 1.227 +# ifdef PNG_READ_sRGB_SUPPORTED 1.228 + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; 1.229 +# else 1.230 + PNG_UNUSED(png_ptr) 1.231 +# endif 1.232 + if (is_screen) 1.233 + output_gamma = PNG_GAMMA_sRGB; 1.234 + else 1.235 + output_gamma = PNG_GAMMA_sRGB_INVERSE; 1.236 + } 1.237 + 1.238 + else if (output_gamma == PNG_GAMMA_MAC_18 || 1.239 + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) 1.240 + { 1.241 + if (is_screen) 1.242 + output_gamma = PNG_GAMMA_MAC_OLD; 1.243 + else 1.244 + output_gamma = PNG_GAMMA_MAC_INVERSE; 1.245 + } 1.246 + 1.247 + return output_gamma; 1.248 +} 1.249 + 1.250 +# ifdef PNG_FLOATING_POINT_SUPPORTED 1.251 +static png_fixed_point 1.252 +convert_gamma_value(png_structrp png_ptr, double output_gamma) 1.253 +{ 1.254 + /* The following silently ignores cases where fixed point (times 100,000) 1.255 + * gamma values are passed to the floating point API. This is safe and it 1.256 + * means the fixed point constants work just fine with the floating point 1.257 + * API. The alternative would just lead to undetected errors and spurious 1.258 + * bug reports. Negative values fail inside the _fixed API unless they 1.259 + * correspond to the flag values. 1.260 + */ 1.261 + if (output_gamma > 0 && output_gamma < 128) 1.262 + output_gamma *= PNG_FP_1; 1.263 + 1.264 + /* This preserves -1 and -2 exactly: */ 1.265 + output_gamma = floor(output_gamma + .5); 1.266 + 1.267 + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) 1.268 + png_fixed_error(png_ptr, "gamma value"); 1.269 + 1.270 + return (png_fixed_point)output_gamma; 1.271 +} 1.272 +# endif 1.273 +#endif /* READ_ALPHA_MODE || READ_GAMMA */ 1.274 + 1.275 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1.276 +void PNGFAPI 1.277 +png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, 1.278 + png_fixed_point output_gamma) 1.279 +{ 1.280 + int compose = 0; 1.281 + png_fixed_point file_gamma; 1.282 + 1.283 + png_debug(1, "in png_set_alpha_mode"); 1.284 + 1.285 + if (!png_rtran_ok(png_ptr, 0)) 1.286 + return; 1.287 + 1.288 + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); 1.289 + 1.290 + /* Validate the value to ensure it is in a reasonable range. The value 1.291 + * is expected to be 1 or greater, but this range test allows for some 1.292 + * viewing correction values. The intent is to weed out users of this API 1.293 + * who use the inverse of the gamma value accidentally! Since some of these 1.294 + * values are reasonable this may have to be changed. 1.295 + */ 1.296 + if (output_gamma < 70000 || output_gamma > 300000) 1.297 + png_error(png_ptr, "output gamma out of expected range"); 1.298 + 1.299 + /* The default file gamma is the inverse of the output gamma; the output 1.300 + * gamma may be changed below so get the file value first: 1.301 + */ 1.302 + file_gamma = png_reciprocal(output_gamma); 1.303 + 1.304 + /* There are really 8 possibilities here, composed of any combination 1.305 + * of: 1.306 + * 1.307 + * premultiply the color channels 1.308 + * do not encode non-opaque pixels 1.309 + * encode the alpha as well as the color channels 1.310 + * 1.311 + * The differences disappear if the input/output ('screen') gamma is 1.0, 1.312 + * because then the encoding is a no-op and there is only the choice of 1.313 + * premultiplying the color channels or not. 1.314 + * 1.315 + * png_set_alpha_mode and png_set_background interact because both use 1.316 + * png_compose to do the work. Calling both is only useful when 1.317 + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along 1.318 + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. 1.319 + */ 1.320 + switch (mode) 1.321 + { 1.322 + case PNG_ALPHA_PNG: /* default: png standard */ 1.323 + /* No compose, but it may be set by png_set_background! */ 1.324 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.325 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.326 + break; 1.327 + 1.328 + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ 1.329 + compose = 1; 1.330 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.331 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.332 + /* The output is linear: */ 1.333 + output_gamma = PNG_FP_1; 1.334 + break; 1.335 + 1.336 + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ 1.337 + compose = 1; 1.338 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.339 + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; 1.340 + /* output_gamma records the encoding of opaque pixels! */ 1.341 + break; 1.342 + 1.343 + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ 1.344 + compose = 1; 1.345 + png_ptr->transformations |= PNG_ENCODE_ALPHA; 1.346 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.347 + break; 1.348 + 1.349 + default: 1.350 + png_error(png_ptr, "invalid alpha mode"); 1.351 + } 1.352 + 1.353 + /* Only set the default gamma if the file gamma has not been set (this has 1.354 + * the side effect that the gamma in a second call to png_set_alpha_mode will 1.355 + * be ignored.) 1.356 + */ 1.357 + if (png_ptr->colorspace.gamma == 0) 1.358 + { 1.359 + png_ptr->colorspace.gamma = file_gamma; 1.360 + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 1.361 + } 1.362 + 1.363 + /* But always set the output gamma: */ 1.364 + png_ptr->screen_gamma = output_gamma; 1.365 + 1.366 + /* Finally, if pre-multiplying, set the background fields to achieve the 1.367 + * desired result. 1.368 + */ 1.369 + if (compose) 1.370 + { 1.371 + /* And obtain alpha pre-multiplication by composing on black: */ 1.372 + memset(&png_ptr->background, 0, (sizeof png_ptr->background)); 1.373 + png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ 1.374 + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; 1.375 + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 1.376 + 1.377 + if (png_ptr->transformations & PNG_COMPOSE) 1.378 + png_error(png_ptr, 1.379 + "conflicting calls to set alpha mode and background"); 1.380 + 1.381 + png_ptr->transformations |= PNG_COMPOSE; 1.382 + } 1.383 +} 1.384 + 1.385 +# ifdef PNG_FLOATING_POINT_SUPPORTED 1.386 +void PNGAPI 1.387 +png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) 1.388 +{ 1.389 + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, 1.390 + output_gamma)); 1.391 +} 1.392 +# endif 1.393 +#endif 1.394 + 1.395 +#ifdef PNG_READ_QUANTIZE_SUPPORTED 1.396 +/* Dither file to 8-bit. Supply a palette, the current number 1.397 + * of elements in the palette, the maximum number of elements 1.398 + * allowed, and a histogram if possible. If the current number 1.399 + * of colors is greater then the maximum number, the palette will be 1.400 + * modified to fit in the maximum number. "full_quantize" indicates 1.401 + * whether we need a quantizing cube set up for RGB images, or if we 1.402 + * simply are reducing the number of colors in a paletted image. 1.403 + */ 1.404 + 1.405 +typedef struct png_dsort_struct 1.406 +{ 1.407 + struct png_dsort_struct * next; 1.408 + png_byte left; 1.409 + png_byte right; 1.410 +} png_dsort; 1.411 +typedef png_dsort * png_dsortp; 1.412 +typedef png_dsort * * png_dsortpp; 1.413 + 1.414 +void PNGAPI 1.415 +png_set_quantize(png_structrp png_ptr, png_colorp palette, 1.416 + int num_palette, int maximum_colors, png_const_uint_16p histogram, 1.417 + int full_quantize) 1.418 +{ 1.419 + png_debug(1, "in png_set_quantize"); 1.420 + 1.421 + if (!png_rtran_ok(png_ptr, 0)) 1.422 + return; 1.423 + 1.424 + png_ptr->transformations |= PNG_QUANTIZE; 1.425 + 1.426 + if (!full_quantize) 1.427 + { 1.428 + int i; 1.429 + 1.430 + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, 1.431 + (png_uint_32)(num_palette * (sizeof (png_byte)))); 1.432 + for (i = 0; i < num_palette; i++) 1.433 + png_ptr->quantize_index[i] = (png_byte)i; 1.434 + } 1.435 + 1.436 + if (num_palette > maximum_colors) 1.437 + { 1.438 + if (histogram != NULL) 1.439 + { 1.440 + /* This is easy enough, just throw out the least used colors. 1.441 + * Perhaps not the best solution, but good enough. 1.442 + */ 1.443 + 1.444 + int i; 1.445 + 1.446 + /* Initialize an array to sort colors */ 1.447 + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, 1.448 + (png_uint_32)(num_palette * (sizeof (png_byte)))); 1.449 + 1.450 + /* Initialize the quantize_sort array */ 1.451 + for (i = 0; i < num_palette; i++) 1.452 + png_ptr->quantize_sort[i] = (png_byte)i; 1.453 + 1.454 + /* Find the least used palette entries by starting a 1.455 + * bubble sort, and running it until we have sorted 1.456 + * out enough colors. Note that we don't care about 1.457 + * sorting all the colors, just finding which are 1.458 + * least used. 1.459 + */ 1.460 + 1.461 + for (i = num_palette - 1; i >= maximum_colors; i--) 1.462 + { 1.463 + int done; /* To stop early if the list is pre-sorted */ 1.464 + int j; 1.465 + 1.466 + done = 1; 1.467 + for (j = 0; j < i; j++) 1.468 + { 1.469 + if (histogram[png_ptr->quantize_sort[j]] 1.470 + < histogram[png_ptr->quantize_sort[j + 1]]) 1.471 + { 1.472 + png_byte t; 1.473 + 1.474 + t = png_ptr->quantize_sort[j]; 1.475 + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; 1.476 + png_ptr->quantize_sort[j + 1] = t; 1.477 + done = 0; 1.478 + } 1.479 + } 1.480 + 1.481 + if (done) 1.482 + break; 1.483 + } 1.484 + 1.485 + /* Swap the palette around, and set up a table, if necessary */ 1.486 + if (full_quantize) 1.487 + { 1.488 + int j = num_palette; 1.489 + 1.490 + /* Put all the useful colors within the max, but don't 1.491 + * move the others. 1.492 + */ 1.493 + for (i = 0; i < maximum_colors; i++) 1.494 + { 1.495 + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 1.496 + { 1.497 + do 1.498 + j--; 1.499 + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 1.500 + 1.501 + palette[i] = palette[j]; 1.502 + } 1.503 + } 1.504 + } 1.505 + else 1.506 + { 1.507 + int j = num_palette; 1.508 + 1.509 + /* Move all the used colors inside the max limit, and 1.510 + * develop a translation table. 1.511 + */ 1.512 + for (i = 0; i < maximum_colors; i++) 1.513 + { 1.514 + /* Only move the colors we need to */ 1.515 + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 1.516 + { 1.517 + png_color tmp_color; 1.518 + 1.519 + do 1.520 + j--; 1.521 + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 1.522 + 1.523 + tmp_color = palette[j]; 1.524 + palette[j] = palette[i]; 1.525 + palette[i] = tmp_color; 1.526 + /* Indicate where the color went */ 1.527 + png_ptr->quantize_index[j] = (png_byte)i; 1.528 + png_ptr->quantize_index[i] = (png_byte)j; 1.529 + } 1.530 + } 1.531 + 1.532 + /* Find closest color for those colors we are not using */ 1.533 + for (i = 0; i < num_palette; i++) 1.534 + { 1.535 + if ((int)png_ptr->quantize_index[i] >= maximum_colors) 1.536 + { 1.537 + int min_d, k, min_k, d_index; 1.538 + 1.539 + /* Find the closest color to one we threw out */ 1.540 + d_index = png_ptr->quantize_index[i]; 1.541 + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 1.542 + for (k = 1, min_k = 0; k < maximum_colors; k++) 1.543 + { 1.544 + int d; 1.545 + 1.546 + d = PNG_COLOR_DIST(palette[d_index], palette[k]); 1.547 + 1.548 + if (d < min_d) 1.549 + { 1.550 + min_d = d; 1.551 + min_k = k; 1.552 + } 1.553 + } 1.554 + /* Point to closest color */ 1.555 + png_ptr->quantize_index[i] = (png_byte)min_k; 1.556 + } 1.557 + } 1.558 + } 1.559 + png_free(png_ptr, png_ptr->quantize_sort); 1.560 + png_ptr->quantize_sort = NULL; 1.561 + } 1.562 + else 1.563 + { 1.564 + /* This is much harder to do simply (and quickly). Perhaps 1.565 + * we need to go through a median cut routine, but those 1.566 + * don't always behave themselves with only a few colors 1.567 + * as input. So we will just find the closest two colors, 1.568 + * and throw out one of them (chosen somewhat randomly). 1.569 + * [We don't understand this at all, so if someone wants to 1.570 + * work on improving it, be our guest - AED, GRP] 1.571 + */ 1.572 + int i; 1.573 + int max_d; 1.574 + int num_new_palette; 1.575 + png_dsortp t; 1.576 + png_dsortpp hash; 1.577 + 1.578 + t = NULL; 1.579 + 1.580 + /* Initialize palette index arrays */ 1.581 + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 1.582 + (png_uint_32)(num_palette * (sizeof (png_byte)))); 1.583 + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 1.584 + (png_uint_32)(num_palette * (sizeof (png_byte)))); 1.585 + 1.586 + /* Initialize the sort array */ 1.587 + for (i = 0; i < num_palette; i++) 1.588 + { 1.589 + png_ptr->index_to_palette[i] = (png_byte)i; 1.590 + png_ptr->palette_to_index[i] = (png_byte)i; 1.591 + } 1.592 + 1.593 + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * 1.594 + (sizeof (png_dsortp)))); 1.595 + 1.596 + num_new_palette = num_palette; 1.597 + 1.598 + /* Initial wild guess at how far apart the farthest pixel 1.599 + * pair we will be eliminating will be. Larger 1.600 + * numbers mean more areas will be allocated, Smaller 1.601 + * numbers run the risk of not saving enough data, and 1.602 + * having to do this all over again. 1.603 + * 1.604 + * I have not done extensive checking on this number. 1.605 + */ 1.606 + max_d = 96; 1.607 + 1.608 + while (num_new_palette > maximum_colors) 1.609 + { 1.610 + for (i = 0; i < num_new_palette - 1; i++) 1.611 + { 1.612 + int j; 1.613 + 1.614 + for (j = i + 1; j < num_new_palette; j++) 1.615 + { 1.616 + int d; 1.617 + 1.618 + d = PNG_COLOR_DIST(palette[i], palette[j]); 1.619 + 1.620 + if (d <= max_d) 1.621 + { 1.622 + 1.623 + t = (png_dsortp)png_malloc_warn(png_ptr, 1.624 + (png_uint_32)(sizeof (png_dsort))); 1.625 + 1.626 + if (t == NULL) 1.627 + break; 1.628 + 1.629 + t->next = hash[d]; 1.630 + t->left = (png_byte)i; 1.631 + t->right = (png_byte)j; 1.632 + hash[d] = t; 1.633 + } 1.634 + } 1.635 + if (t == NULL) 1.636 + break; 1.637 + } 1.638 + 1.639 + if (t != NULL) 1.640 + for (i = 0; i <= max_d; i++) 1.641 + { 1.642 + if (hash[i] != NULL) 1.643 + { 1.644 + png_dsortp p; 1.645 + 1.646 + for (p = hash[i]; p; p = p->next) 1.647 + { 1.648 + if ((int)png_ptr->index_to_palette[p->left] 1.649 + < num_new_palette && 1.650 + (int)png_ptr->index_to_palette[p->right] 1.651 + < num_new_palette) 1.652 + { 1.653 + int j, next_j; 1.654 + 1.655 + if (num_new_palette & 0x01) 1.656 + { 1.657 + j = p->left; 1.658 + next_j = p->right; 1.659 + } 1.660 + else 1.661 + { 1.662 + j = p->right; 1.663 + next_j = p->left; 1.664 + } 1.665 + 1.666 + num_new_palette--; 1.667 + palette[png_ptr->index_to_palette[j]] 1.668 + = palette[num_new_palette]; 1.669 + if (!full_quantize) 1.670 + { 1.671 + int k; 1.672 + 1.673 + for (k = 0; k < num_palette; k++) 1.674 + { 1.675 + if (png_ptr->quantize_index[k] == 1.676 + png_ptr->index_to_palette[j]) 1.677 + png_ptr->quantize_index[k] = 1.678 + png_ptr->index_to_palette[next_j]; 1.679 + 1.680 + if ((int)png_ptr->quantize_index[k] == 1.681 + num_new_palette) 1.682 + png_ptr->quantize_index[k] = 1.683 + png_ptr->index_to_palette[j]; 1.684 + } 1.685 + } 1.686 + 1.687 + png_ptr->index_to_palette[png_ptr->palette_to_index 1.688 + [num_new_palette]] = png_ptr->index_to_palette[j]; 1.689 + 1.690 + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 1.691 + = png_ptr->palette_to_index[num_new_palette]; 1.692 + 1.693 + png_ptr->index_to_palette[j] = 1.694 + (png_byte)num_new_palette; 1.695 + 1.696 + png_ptr->palette_to_index[num_new_palette] = 1.697 + (png_byte)j; 1.698 + } 1.699 + if (num_new_palette <= maximum_colors) 1.700 + break; 1.701 + } 1.702 + if (num_new_palette <= maximum_colors) 1.703 + break; 1.704 + } 1.705 + } 1.706 + 1.707 + for (i = 0; i < 769; i++) 1.708 + { 1.709 + if (hash[i] != NULL) 1.710 + { 1.711 + png_dsortp p = hash[i]; 1.712 + while (p) 1.713 + { 1.714 + t = p->next; 1.715 + png_free(png_ptr, p); 1.716 + p = t; 1.717 + } 1.718 + } 1.719 + hash[i] = 0; 1.720 + } 1.721 + max_d += 96; 1.722 + } 1.723 + png_free(png_ptr, hash); 1.724 + png_free(png_ptr, png_ptr->palette_to_index); 1.725 + png_free(png_ptr, png_ptr->index_to_palette); 1.726 + png_ptr->palette_to_index = NULL; 1.727 + png_ptr->index_to_palette = NULL; 1.728 + } 1.729 + num_palette = maximum_colors; 1.730 + } 1.731 + if (png_ptr->palette == NULL) 1.732 + { 1.733 + png_ptr->palette = palette; 1.734 + } 1.735 + png_ptr->num_palette = (png_uint_16)num_palette; 1.736 + 1.737 + if (full_quantize) 1.738 + { 1.739 + int i; 1.740 + png_bytep distance; 1.741 + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + 1.742 + PNG_QUANTIZE_BLUE_BITS; 1.743 + int num_red = (1 << PNG_QUANTIZE_RED_BITS); 1.744 + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); 1.745 + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); 1.746 + png_size_t num_entries = ((png_size_t)1 << total_bits); 1.747 + 1.748 + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, 1.749 + (png_uint_32)(num_entries * (sizeof (png_byte)))); 1.750 + 1.751 + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 1.752 + (sizeof (png_byte)))); 1.753 + 1.754 + memset(distance, 0xff, num_entries * (sizeof (png_byte))); 1.755 + 1.756 + for (i = 0; i < num_palette; i++) 1.757 + { 1.758 + int ir, ig, ib; 1.759 + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); 1.760 + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); 1.761 + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); 1.762 + 1.763 + for (ir = 0; ir < num_red; ir++) 1.764 + { 1.765 + /* int dr = abs(ir - r); */ 1.766 + int dr = ((ir > r) ? ir - r : r - ir); 1.767 + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + 1.768 + PNG_QUANTIZE_GREEN_BITS)); 1.769 + 1.770 + for (ig = 0; ig < num_green; ig++) 1.771 + { 1.772 + /* int dg = abs(ig - g); */ 1.773 + int dg = ((ig > g) ? ig - g : g - ig); 1.774 + int dt = dr + dg; 1.775 + int dm = ((dr > dg) ? dr : dg); 1.776 + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); 1.777 + 1.778 + for (ib = 0; ib < num_blue; ib++) 1.779 + { 1.780 + int d_index = index_g | ib; 1.781 + /* int db = abs(ib - b); */ 1.782 + int db = ((ib > b) ? ib - b : b - ib); 1.783 + int dmax = ((dm > db) ? dm : db); 1.784 + int d = dmax + dt + db; 1.785 + 1.786 + if (d < (int)distance[d_index]) 1.787 + { 1.788 + distance[d_index] = (png_byte)d; 1.789 + png_ptr->palette_lookup[d_index] = (png_byte)i; 1.790 + } 1.791 + } 1.792 + } 1.793 + } 1.794 + } 1.795 + 1.796 + png_free(png_ptr, distance); 1.797 + } 1.798 +} 1.799 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ 1.800 + 1.801 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.802 +void PNGFAPI 1.803 +png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, 1.804 + png_fixed_point file_gamma) 1.805 +{ 1.806 + png_debug(1, "in png_set_gamma_fixed"); 1.807 + 1.808 + if (!png_rtran_ok(png_ptr, 0)) 1.809 + return; 1.810 + 1.811 + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ 1.812 + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); 1.813 + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); 1.814 + 1.815 + /* Checking the gamma values for being >0 was added in 1.5.4 along with the 1.816 + * premultiplied alpha support; this actually hides an undocumented feature 1.817 + * of the previous implementation which allowed gamma processing to be 1.818 + * disabled in background handling. There is no evidence (so far) that this 1.819 + * was being used; however, png_set_background itself accepted and must still 1.820 + * accept '0' for the gamma value it takes, because it isn't always used. 1.821 + * 1.822 + * Since this is an API change (albeit a very minor one that removes an 1.823 + * undocumented API feature) the following checks were only enabled in 1.824 + * libpng-1.6.0. 1.825 + */ 1.826 + if (file_gamma <= 0) 1.827 + png_error(png_ptr, "invalid file gamma in png_set_gamma"); 1.828 + 1.829 + if (scrn_gamma <= 0) 1.830 + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); 1.831 + 1.832 + /* Set the gamma values unconditionally - this overrides the value in the PNG 1.833 + * file if a gAMA chunk was present. png_set_alpha_mode provides a 1.834 + * different, easier, way to default the file gamma. 1.835 + */ 1.836 + png_ptr->colorspace.gamma = file_gamma; 1.837 + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 1.838 + png_ptr->screen_gamma = scrn_gamma; 1.839 +} 1.840 + 1.841 +# ifdef PNG_FLOATING_POINT_SUPPORTED 1.842 +void PNGAPI 1.843 +png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) 1.844 +{ 1.845 + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), 1.846 + convert_gamma_value(png_ptr, file_gamma)); 1.847 +} 1.848 +# endif /* FLOATING_POINT_SUPPORTED */ 1.849 +#endif /* READ_GAMMA */ 1.850 + 1.851 +#ifdef PNG_READ_EXPAND_SUPPORTED 1.852 +/* Expand paletted images to RGB, expand grayscale images of 1.853 + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 1.854 + * to alpha channels. 1.855 + */ 1.856 +void PNGAPI 1.857 +png_set_expand(png_structrp png_ptr) 1.858 +{ 1.859 + png_debug(1, "in png_set_expand"); 1.860 + 1.861 + if (!png_rtran_ok(png_ptr, 0)) 1.862 + return; 1.863 + 1.864 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.865 +} 1.866 + 1.867 +/* GRR 19990627: the following three functions currently are identical 1.868 + * to png_set_expand(). However, it is entirely reasonable that someone 1.869 + * might wish to expand an indexed image to RGB but *not* expand a single, 1.870 + * fully transparent palette entry to a full alpha channel--perhaps instead 1.871 + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 1.872 + * the transparent color with a particular RGB value, or drop tRNS entirely. 1.873 + * IOW, a future version of the library may make the transformations flag 1.874 + * a bit more fine-grained, with separate bits for each of these three 1.875 + * functions. 1.876 + * 1.877 + * More to the point, these functions make it obvious what libpng will be 1.878 + * doing, whereas "expand" can (and does) mean any number of things. 1.879 + * 1.880 + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified 1.881 + * to expand only the sample depth but not to expand the tRNS to alpha 1.882 + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). 1.883 + */ 1.884 + 1.885 +/* Expand paletted images to RGB. */ 1.886 +void PNGAPI 1.887 +png_set_palette_to_rgb(png_structrp png_ptr) 1.888 +{ 1.889 + png_debug(1, "in png_set_palette_to_rgb"); 1.890 + 1.891 + if (!png_rtran_ok(png_ptr, 0)) 1.892 + return; 1.893 + 1.894 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.895 +} 1.896 + 1.897 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ 1.898 +void PNGAPI 1.899 +png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) 1.900 +{ 1.901 + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); 1.902 + 1.903 + if (!png_rtran_ok(png_ptr, 0)) 1.904 + return; 1.905 + 1.906 + png_ptr->transformations |= PNG_EXPAND; 1.907 +} 1.908 + 1.909 +/* Expand tRNS chunks to alpha channels. */ 1.910 +void PNGAPI 1.911 +png_set_tRNS_to_alpha(png_structrp png_ptr) 1.912 +{ 1.913 + png_debug(1, "in png_set_tRNS_to_alpha"); 1.914 + 1.915 + if (!png_rtran_ok(png_ptr, 0)) 1.916 + return; 1.917 + 1.918 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.919 +} 1.920 +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ 1.921 + 1.922 +#ifdef PNG_READ_EXPAND_16_SUPPORTED 1.923 +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise 1.924 + * it may not work correctly.) 1.925 + */ 1.926 +void PNGAPI 1.927 +png_set_expand_16(png_structrp png_ptr) 1.928 +{ 1.929 + png_debug(1, "in png_set_expand_16"); 1.930 + 1.931 + if (!png_rtran_ok(png_ptr, 0)) 1.932 + return; 1.933 + 1.934 + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); 1.935 +} 1.936 +#endif 1.937 + 1.938 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.939 +void PNGAPI 1.940 +png_set_gray_to_rgb(png_structrp png_ptr) 1.941 +{ 1.942 + png_debug(1, "in png_set_gray_to_rgb"); 1.943 + 1.944 + if (!png_rtran_ok(png_ptr, 0)) 1.945 + return; 1.946 + 1.947 + /* Because rgb must be 8 bits or more: */ 1.948 + png_set_expand_gray_1_2_4_to_8(png_ptr); 1.949 + png_ptr->transformations |= PNG_GRAY_TO_RGB; 1.950 +} 1.951 +#endif 1.952 + 1.953 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.954 +void PNGFAPI 1.955 +png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, 1.956 + png_fixed_point red, png_fixed_point green) 1.957 +{ 1.958 + png_debug(1, "in png_set_rgb_to_gray"); 1.959 + 1.960 + /* Need the IHDR here because of the check on color_type below. */ 1.961 + /* TODO: fix this */ 1.962 + if (!png_rtran_ok(png_ptr, 1)) 1.963 + return; 1.964 + 1.965 + switch(error_action) 1.966 + { 1.967 + case PNG_ERROR_ACTION_NONE: 1.968 + png_ptr->transformations |= PNG_RGB_TO_GRAY; 1.969 + break; 1.970 + 1.971 + case PNG_ERROR_ACTION_WARN: 1.972 + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 1.973 + break; 1.974 + 1.975 + case PNG_ERROR_ACTION_ERROR: 1.976 + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 1.977 + break; 1.978 + 1.979 + default: 1.980 + png_error(png_ptr, "invalid error action to rgb_to_gray"); 1.981 + break; 1.982 + } 1.983 + 1.984 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.985 +#ifdef PNG_READ_EXPAND_SUPPORTED 1.986 + png_ptr->transformations |= PNG_EXPAND; 1.987 +#else 1.988 + { 1.989 + /* Make this an error in 1.6 because otherwise the application may assume 1.990 + * that it just worked and get a memory overwrite. 1.991 + */ 1.992 + png_error(png_ptr, 1.993 + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); 1.994 + 1.995 + /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ 1.996 + } 1.997 +#endif 1.998 + { 1.999 + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) 1.1000 + { 1.1001 + png_uint_16 red_int, green_int; 1.1002 + 1.1003 + /* NOTE: this calculation does not round, but this behavior is retained 1.1004 + * for consistency, the inaccuracy is very small. The code here always 1.1005 + * overwrites the coefficients, regardless of whether they have been 1.1006 + * defaulted or set already. 1.1007 + */ 1.1008 + red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); 1.1009 + green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); 1.1010 + 1.1011 + png_ptr->rgb_to_gray_red_coeff = red_int; 1.1012 + png_ptr->rgb_to_gray_green_coeff = green_int; 1.1013 + png_ptr->rgb_to_gray_coefficients_set = 1; 1.1014 + } 1.1015 + 1.1016 + else 1.1017 + { 1.1018 + if (red >= 0 && green >= 0) 1.1019 + png_app_warning(png_ptr, 1.1020 + "ignoring out of range rgb_to_gray coefficients"); 1.1021 + 1.1022 + /* Use the defaults, from the cHRM chunk if set, else the historical 1.1023 + * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See 1.1024 + * png_do_rgb_to_gray for more discussion of the values. In this case 1.1025 + * the coefficients are not marked as 'set' and are not overwritten if 1.1026 + * something has already provided a default. 1.1027 + */ 1.1028 + if (png_ptr->rgb_to_gray_red_coeff == 0 && 1.1029 + png_ptr->rgb_to_gray_green_coeff == 0) 1.1030 + { 1.1031 + png_ptr->rgb_to_gray_red_coeff = 6968; 1.1032 + png_ptr->rgb_to_gray_green_coeff = 23434; 1.1033 + /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ 1.1034 + } 1.1035 + } 1.1036 + } 1.1037 +} 1.1038 + 1.1039 +#ifdef PNG_FLOATING_POINT_SUPPORTED 1.1040 +/* Convert a RGB image to a grayscale of the same width. This allows us, 1.1041 + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 1.1042 + */ 1.1043 + 1.1044 +void PNGAPI 1.1045 +png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, 1.1046 + double green) 1.1047 +{ 1.1048 + png_set_rgb_to_gray_fixed(png_ptr, error_action, 1.1049 + png_fixed(png_ptr, red, "rgb to gray red coefficient"), 1.1050 + png_fixed(png_ptr, green, "rgb to gray green coefficient")); 1.1051 +} 1.1052 +#endif /* FLOATING POINT */ 1.1053 + 1.1054 +#endif /* RGB_TO_GRAY */ 1.1055 + 1.1056 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 1.1057 + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 1.1058 +void PNGAPI 1.1059 +png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr 1.1060 + read_user_transform_fn) 1.1061 +{ 1.1062 + png_debug(1, "in png_set_read_user_transform_fn"); 1.1063 + 1.1064 +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1.1065 + png_ptr->transformations |= PNG_USER_TRANSFORM; 1.1066 + png_ptr->read_user_transform_fn = read_user_transform_fn; 1.1067 +#endif 1.1068 +} 1.1069 +#endif 1.1070 + 1.1071 +#ifdef PNG_READ_TRANSFORMS_SUPPORTED 1.1072 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.1073 +/* In the case of gamma transformations only do transformations on images where 1.1074 + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it 1.1075 + * slows things down slightly, and also needlessly introduces small errors. 1.1076 + */ 1.1077 +static int /* PRIVATE */ 1.1078 +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) 1.1079 +{ 1.1080 + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma 1.1081 + * correction as a difference of the overall transform from 1.0 1.1082 + * 1.1083 + * We want to compare the threshold with s*f - 1, if we get 1.1084 + * overflow here it is because of wacky gamma values so we 1.1085 + * turn on processing anyway. 1.1086 + */ 1.1087 + png_fixed_point gtest; 1.1088 + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || 1.1089 + png_gamma_significant(gtest); 1.1090 +} 1.1091 +#endif 1.1092 + 1.1093 +/* Initialize everything needed for the read. This includes modifying 1.1094 + * the palette. 1.1095 + */ 1.1096 + 1.1097 +/*For the moment 'png_init_palette_transformations' and 1.1098 + * 'png_init_rgb_transformations' only do some flag canceling optimizations. 1.1099 + * The intent is that these two routines should have palette or rgb operations 1.1100 + * extracted from 'png_init_read_transformations'. 1.1101 + */ 1.1102 +static void /* PRIVATE */ 1.1103 +png_init_palette_transformations(png_structrp png_ptr) 1.1104 +{ 1.1105 + /* Called to handle the (input) palette case. In png_do_read_transformations 1.1106 + * the first step is to expand the palette if requested, so this code must 1.1107 + * take care to only make changes that are invariant with respect to the 1.1108 + * palette expansion, or only do them if there is no expansion. 1.1109 + * 1.1110 + * STRIP_ALPHA has already been handled in the caller (by setting num_trans 1.1111 + * to 0.) 1.1112 + */ 1.1113 + int input_has_alpha = 0; 1.1114 + int input_has_transparency = 0; 1.1115 + 1.1116 + if (png_ptr->num_trans > 0) 1.1117 + { 1.1118 + int i; 1.1119 + 1.1120 + /* Ignore if all the entries are opaque (unlikely!) */ 1.1121 + for (i=0; i<png_ptr->num_trans; ++i) 1.1122 + { 1.1123 + if (png_ptr->trans_alpha[i] == 255) 1.1124 + continue; 1.1125 + else if (png_ptr->trans_alpha[i] == 0) 1.1126 + input_has_transparency = 1; 1.1127 + else 1.1128 + { 1.1129 + input_has_transparency = 1; 1.1130 + input_has_alpha = 1; 1.1131 + break; 1.1132 + } 1.1133 + } 1.1134 + } 1.1135 + 1.1136 + /* If no alpha we can optimize. */ 1.1137 + if (!input_has_alpha) 1.1138 + { 1.1139 + /* Any alpha means background and associative alpha processing is 1.1140 + * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA 1.1141 + * and ENCODE_ALPHA are irrelevant. 1.1142 + */ 1.1143 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.1144 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.1145 + 1.1146 + if (!input_has_transparency) 1.1147 + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 1.1148 + } 1.1149 + 1.1150 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1151 + /* png_set_background handling - deals with the complexity of whether the 1.1152 + * background color is in the file format or the screen format in the case 1.1153 + * where an 'expand' will happen. 1.1154 + */ 1.1155 + 1.1156 + /* The following code cannot be entered in the alpha pre-multiplication case 1.1157 + * because PNG_BACKGROUND_EXPAND is cancelled below. 1.1158 + */ 1.1159 + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.1160 + (png_ptr->transformations & PNG_EXPAND)) 1.1161 + { 1.1162 + { 1.1163 + png_ptr->background.red = 1.1164 + png_ptr->palette[png_ptr->background.index].red; 1.1165 + png_ptr->background.green = 1.1166 + png_ptr->palette[png_ptr->background.index].green; 1.1167 + png_ptr->background.blue = 1.1168 + png_ptr->palette[png_ptr->background.index].blue; 1.1169 + 1.1170 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1.1171 + if (png_ptr->transformations & PNG_INVERT_ALPHA) 1.1172 + { 1.1173 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.1174 + { 1.1175 + /* Invert the alpha channel (in tRNS) unless the pixels are 1.1176 + * going to be expanded, in which case leave it for later 1.1177 + */ 1.1178 + int i, istop = png_ptr->num_trans; 1.1179 + 1.1180 + for (i=0; i<istop; i++) 1.1181 + png_ptr->trans_alpha[i] = (png_byte)(255 - 1.1182 + png_ptr->trans_alpha[i]); 1.1183 + } 1.1184 + } 1.1185 +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ 1.1186 + } 1.1187 + } /* background expand and (therefore) no alpha association. */ 1.1188 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ 1.1189 +} 1.1190 + 1.1191 +static void /* PRIVATE */ 1.1192 +png_init_rgb_transformations(png_structrp png_ptr) 1.1193 +{ 1.1194 + /* Added to libpng-1.5.4: check the color type to determine whether there 1.1195 + * is any alpha or transparency in the image and simply cancel the 1.1196 + * background and alpha mode stuff if there isn't. 1.1197 + */ 1.1198 + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; 1.1199 + int input_has_transparency = png_ptr->num_trans > 0; 1.1200 + 1.1201 + /* If no alpha we can optimize. */ 1.1202 + if (!input_has_alpha) 1.1203 + { 1.1204 + /* Any alpha means background and associative alpha processing is 1.1205 + * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA 1.1206 + * and ENCODE_ALPHA are irrelevant. 1.1207 + */ 1.1208 +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1.1209 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.1210 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.1211 +# endif 1.1212 + 1.1213 + if (!input_has_transparency) 1.1214 + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 1.1215 + } 1.1216 + 1.1217 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1218 + /* png_set_background handling - deals with the complexity of whether the 1.1219 + * background color is in the file format or the screen format in the case 1.1220 + * where an 'expand' will happen. 1.1221 + */ 1.1222 + 1.1223 + /* The following code cannot be entered in the alpha pre-multiplication case 1.1224 + * because PNG_BACKGROUND_EXPAND is cancelled below. 1.1225 + */ 1.1226 + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.1227 + (png_ptr->transformations & PNG_EXPAND) && 1.1228 + !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) 1.1229 + /* i.e., GRAY or GRAY_ALPHA */ 1.1230 + { 1.1231 + { 1.1232 + /* Expand background and tRNS chunks */ 1.1233 + int gray = png_ptr->background.gray; 1.1234 + int trans_gray = png_ptr->trans_color.gray; 1.1235 + 1.1236 + switch (png_ptr->bit_depth) 1.1237 + { 1.1238 + case 1: 1.1239 + gray *= 0xff; 1.1240 + trans_gray *= 0xff; 1.1241 + break; 1.1242 + 1.1243 + case 2: 1.1244 + gray *= 0x55; 1.1245 + trans_gray *= 0x55; 1.1246 + break; 1.1247 + 1.1248 + case 4: 1.1249 + gray *= 0x11; 1.1250 + trans_gray *= 0x11; 1.1251 + break; 1.1252 + 1.1253 + default: 1.1254 + 1.1255 + case 8: 1.1256 + /* FALL THROUGH (Already 8 bits) */ 1.1257 + 1.1258 + case 16: 1.1259 + /* Already a full 16 bits */ 1.1260 + break; 1.1261 + } 1.1262 + 1.1263 + png_ptr->background.red = png_ptr->background.green = 1.1264 + png_ptr->background.blue = (png_uint_16)gray; 1.1265 + 1.1266 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.1267 + { 1.1268 + png_ptr->trans_color.red = png_ptr->trans_color.green = 1.1269 + png_ptr->trans_color.blue = (png_uint_16)trans_gray; 1.1270 + } 1.1271 + } 1.1272 + } /* background expand and (therefore) no alpha association. */ 1.1273 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ 1.1274 +} 1.1275 + 1.1276 +void /* PRIVATE */ 1.1277 +png_init_read_transformations(png_structrp png_ptr) 1.1278 +{ 1.1279 + png_debug(1, "in png_init_read_transformations"); 1.1280 + 1.1281 + /* This internal function is called from png_read_start_row in pngrutil.c 1.1282 + * and it is called before the 'rowbytes' calculation is done, so the code 1.1283 + * in here can change or update the transformations flags. 1.1284 + * 1.1285 + * First do updates that do not depend on the details of the PNG image data 1.1286 + * being processed. 1.1287 + */ 1.1288 + 1.1289 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.1290 + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds 1.1291 + * png_set_alpha_mode and this is another source for a default file gamma so 1.1292 + * the test needs to be performed later - here. In addition prior to 1.5.4 1.1293 + * the tests were repeated for the PALETTE color type here - this is no 1.1294 + * longer necessary (and doesn't seem to have been necessary before.) 1.1295 + */ 1.1296 + { 1.1297 + /* The following temporary indicates if overall gamma correction is 1.1298 + * required. 1.1299 + */ 1.1300 + int gamma_correction = 0; 1.1301 + 1.1302 + if (png_ptr->colorspace.gamma != 0) /* has been set */ 1.1303 + { 1.1304 + if (png_ptr->screen_gamma != 0) /* screen set too */ 1.1305 + gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, 1.1306 + png_ptr->screen_gamma); 1.1307 + 1.1308 + else 1.1309 + /* Assume the output matches the input; a long time default behavior 1.1310 + * of libpng, although the standard has nothing to say about this. 1.1311 + */ 1.1312 + png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); 1.1313 + } 1.1314 + 1.1315 + else if (png_ptr->screen_gamma != 0) 1.1316 + /* The converse - assume the file matches the screen, note that this 1.1317 + * perhaps undesireable default can (from 1.5.4) be changed by calling 1.1318 + * png_set_alpha_mode (even if the alpha handling mode isn't required 1.1319 + * or isn't changed from the default.) 1.1320 + */ 1.1321 + png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); 1.1322 + 1.1323 + else /* neither are set */ 1.1324 + /* Just in case the following prevents any processing - file and screen 1.1325 + * are both assumed to be linear and there is no way to introduce a 1.1326 + * third gamma value other than png_set_background with 'UNIQUE', and, 1.1327 + * prior to 1.5.4 1.1328 + */ 1.1329 + png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; 1.1330 + 1.1331 + /* We have a gamma value now. */ 1.1332 + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 1.1333 + 1.1334 + /* Now turn the gamma transformation on or off as appropriate. Notice 1.1335 + * that PNG_GAMMA just refers to the file->screen correction. Alpha 1.1336 + * composition may independently cause gamma correction because it needs 1.1337 + * linear data (e.g. if the file has a gAMA chunk but the screen gamma 1.1338 + * hasn't been specified.) In any case this flag may get turned off in 1.1339 + * the code immediately below if the transform can be handled outside the 1.1340 + * row loop. 1.1341 + */ 1.1342 + if (gamma_correction) 1.1343 + png_ptr->transformations |= PNG_GAMMA; 1.1344 + 1.1345 + else 1.1346 + png_ptr->transformations &= ~PNG_GAMMA; 1.1347 + } 1.1348 +#endif 1.1349 + 1.1350 + /* Certain transformations have the effect of preventing other 1.1351 + * transformations that happen afterward in png_do_read_transformations, 1.1352 + * resolve the interdependencies here. From the code of 1.1353 + * png_do_read_transformations the order is: 1.1354 + * 1.1355 + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) 1.1356 + * 2) PNG_STRIP_ALPHA (if no compose) 1.1357 + * 3) PNG_RGB_TO_GRAY 1.1358 + * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY 1.1359 + * 5) PNG_COMPOSE 1.1360 + * 6) PNG_GAMMA 1.1361 + * 7) PNG_STRIP_ALPHA (if compose) 1.1362 + * 8) PNG_ENCODE_ALPHA 1.1363 + * 9) PNG_SCALE_16_TO_8 1.1364 + * 10) PNG_16_TO_8 1.1365 + * 11) PNG_QUANTIZE (converts to palette) 1.1366 + * 12) PNG_EXPAND_16 1.1367 + * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY 1.1368 + * 14) PNG_INVERT_MONO 1.1369 + * 15) PNG_INVERT_ALPHA 1.1370 + * 16) PNG_SHIFT 1.1371 + * 17) PNG_PACK 1.1372 + * 18) PNG_BGR 1.1373 + * 19) PNG_PACKSWAP 1.1374 + * 20) PNG_FILLER (includes PNG_ADD_ALPHA) 1.1375 + * 21) PNG_SWAP_ALPHA 1.1376 + * 22) PNG_SWAP_BYTES 1.1377 + * 23) PNG_USER_TRANSFORM [must be last] 1.1378 + */ 1.1379 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1.1380 + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 1.1381 + !(png_ptr->transformations & PNG_COMPOSE)) 1.1382 + { 1.1383 + /* Stripping the alpha channel happens immediately after the 'expand' 1.1384 + * transformations, before all other transformation, so it cancels out 1.1385 + * the alpha handling. It has the side effect negating the effect of 1.1386 + * PNG_EXPAND_tRNS too: 1.1387 + */ 1.1388 + png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | 1.1389 + PNG_EXPAND_tRNS); 1.1390 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.1391 + 1.1392 + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen 1.1393 + * so transparency information would remain just so long as it wasn't 1.1394 + * expanded. This produces unexpected API changes if the set of things 1.1395 + * that do PNG_EXPAND_tRNS changes (perfectly possible given the 1.1396 + * documentation - which says ask for what you want, accept what you 1.1397 + * get.) This makes the behavior consistent from 1.5.4: 1.1398 + */ 1.1399 + png_ptr->num_trans = 0; 1.1400 + } 1.1401 +#endif /* STRIP_ALPHA supported, no COMPOSE */ 1.1402 + 1.1403 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1.1404 + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA 1.1405 + * settings will have no effect. 1.1406 + */ 1.1407 + if (!png_gamma_significant(png_ptr->screen_gamma)) 1.1408 + { 1.1409 + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1.1410 + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1.1411 + } 1.1412 +#endif 1.1413 + 1.1414 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.1415 + /* Make sure the coefficients for the rgb to gray conversion are set 1.1416 + * appropriately. 1.1417 + */ 1.1418 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.1419 + png_colorspace_set_rgb_coefficients(png_ptr); 1.1420 +#endif 1.1421 + 1.1422 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.1423 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1424 + /* Detect gray background and attempt to enable optimization for 1.1425 + * gray --> RGB case. 1.1426 + * 1.1427 + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 1.1428 + * RGB_ALPHA (in which case need_expand is superfluous anyway), the 1.1429 + * background color might actually be gray yet not be flagged as such. 1.1430 + * This is not a problem for the current code, which uses 1.1431 + * PNG_BACKGROUND_IS_GRAY only to decide when to do the 1.1432 + * png_do_gray_to_rgb() transformation. 1.1433 + * 1.1434 + * TODO: this code needs to be revised to avoid the complexity and 1.1435 + * interdependencies. The color type of the background should be recorded in 1.1436 + * png_set_background, along with the bit depth, then the code has a record 1.1437 + * of exactly what color space the background is currently in. 1.1438 + */ 1.1439 + if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) 1.1440 + { 1.1441 + /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if 1.1442 + * the file was grayscale the background value is gray. 1.1443 + */ 1.1444 + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) 1.1445 + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1.1446 + } 1.1447 + 1.1448 + else if (png_ptr->transformations & PNG_COMPOSE) 1.1449 + { 1.1450 + /* PNG_COMPOSE: png_set_background was called with need_expand false, 1.1451 + * so the color is in the color space of the output or png_set_alpha_mode 1.1452 + * was called and the color is black. Ignore RGB_TO_GRAY because that 1.1453 + * happens before GRAY_TO_RGB. 1.1454 + */ 1.1455 + if (png_ptr->transformations & PNG_GRAY_TO_RGB) 1.1456 + { 1.1457 + if (png_ptr->background.red == png_ptr->background.green && 1.1458 + png_ptr->background.red == png_ptr->background.blue) 1.1459 + { 1.1460 + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1.1461 + png_ptr->background.gray = png_ptr->background.red; 1.1462 + } 1.1463 + } 1.1464 + } 1.1465 +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ 1.1466 +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ 1.1467 + 1.1468 + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations 1.1469 + * can be performed directly on the palette, and some (such as rgb to gray) 1.1470 + * can be optimized inside the palette. This is particularly true of the 1.1471 + * composite (background and alpha) stuff, which can be pretty much all done 1.1472 + * in the palette even if the result is expanded to RGB or gray afterward. 1.1473 + * 1.1474 + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and 1.1475 + * earlier and the palette stuff is actually handled on the first row. This 1.1476 + * leads to the reported bug that the palette returned by png_get_PLTE is not 1.1477 + * updated. 1.1478 + */ 1.1479 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.1480 + png_init_palette_transformations(png_ptr); 1.1481 + 1.1482 + else 1.1483 + png_init_rgb_transformations(png_ptr); 1.1484 + 1.1485 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1.1486 + defined(PNG_READ_EXPAND_16_SUPPORTED) 1.1487 + if ((png_ptr->transformations & PNG_EXPAND_16) && 1.1488 + (png_ptr->transformations & PNG_COMPOSE) && 1.1489 + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.1490 + png_ptr->bit_depth != 16) 1.1491 + { 1.1492 + /* TODO: fix this. Because the expand_16 operation is after the compose 1.1493 + * handling the background color must be 8, not 16, bits deep, but the 1.1494 + * application will supply a 16-bit value so reduce it here. 1.1495 + * 1.1496 + * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at 1.1497 + * present, so that case is ok (until do_expand_16 is moved.) 1.1498 + * 1.1499 + * NOTE: this discards the low 16 bits of the user supplied background 1.1500 + * color, but until expand_16 works properly there is no choice! 1.1501 + */ 1.1502 +# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x)) 1.1503 + CHOP(png_ptr->background.red); 1.1504 + CHOP(png_ptr->background.green); 1.1505 + CHOP(png_ptr->background.blue); 1.1506 + CHOP(png_ptr->background.gray); 1.1507 +# undef CHOP 1.1508 + } 1.1509 +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ 1.1510 + 1.1511 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1.1512 + (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ 1.1513 + defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) 1.1514 + if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && 1.1515 + (png_ptr->transformations & PNG_COMPOSE) && 1.1516 + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.1517 + png_ptr->bit_depth == 16) 1.1518 + { 1.1519 + /* On the other hand, if a 16-bit file is to be reduced to 8-bits per 1.1520 + * component this will also happen after PNG_COMPOSE and so the background 1.1521 + * color must be pre-expanded here. 1.1522 + * 1.1523 + * TODO: fix this too. 1.1524 + */ 1.1525 + png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); 1.1526 + png_ptr->background.green = 1.1527 + (png_uint_16)(png_ptr->background.green * 257); 1.1528 + png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); 1.1529 + png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); 1.1530 + } 1.1531 +#endif 1.1532 + 1.1533 + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the 1.1534 + * background support (see the comments in scripts/pnglibconf.dfa), this 1.1535 + * allows pre-multiplication of the alpha channel to be implemented as 1.1536 + * compositing on black. This is probably sub-optimal and has been done in 1.1537 + * 1.5.4 betas simply to enable external critique and testing (i.e. to 1.1538 + * implement the new API quickly, without lots of internal changes.) 1.1539 + */ 1.1540 + 1.1541 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.1542 +# ifdef PNG_READ_BACKGROUND_SUPPORTED 1.1543 + /* Includes ALPHA_MODE */ 1.1544 + png_ptr->background_1 = png_ptr->background; 1.1545 +# endif 1.1546 + 1.1547 + /* This needs to change - in the palette image case a whole set of tables are 1.1548 + * built when it would be quicker to just calculate the correct value for 1.1549 + * each palette entry directly. Also, the test is too tricky - why check 1.1550 + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that 1.1551 + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the 1.1552 + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction 1.1553 + * the gamma tables will not be built even if composition is required on a 1.1554 + * gamma encoded value. 1.1555 + * 1.1556 + * In 1.5.4 this is addressed below by an additional check on the individual 1.1557 + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the 1.1558 + * tables. 1.1559 + */ 1.1560 + if ((png_ptr->transformations & PNG_GAMMA) 1.1561 + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) 1.1562 + && (png_gamma_significant(png_ptr->colorspace.gamma) || 1.1563 + png_gamma_significant(png_ptr->screen_gamma))) 1.1564 + || ((png_ptr->transformations & PNG_COMPOSE) 1.1565 + && (png_gamma_significant(png_ptr->colorspace.gamma) 1.1566 + || png_gamma_significant(png_ptr->screen_gamma) 1.1567 +# ifdef PNG_READ_BACKGROUND_SUPPORTED 1.1568 + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE 1.1569 + && png_gamma_significant(png_ptr->background_gamma)) 1.1570 +# endif 1.1571 + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) 1.1572 + && png_gamma_significant(png_ptr->screen_gamma)) 1.1573 + ) 1.1574 + { 1.1575 + png_build_gamma_table(png_ptr, png_ptr->bit_depth); 1.1576 + 1.1577 +#ifdef PNG_READ_BACKGROUND_SUPPORTED 1.1578 + if (png_ptr->transformations & PNG_COMPOSE) 1.1579 + { 1.1580 + /* Issue a warning about this combination: because RGB_TO_GRAY is 1.1581 + * optimized to do the gamma transform if present yet do_background has 1.1582 + * to do the same thing if both options are set a 1.1583 + * double-gamma-correction happens. This is true in all versions of 1.1584 + * libpng to date. 1.1585 + */ 1.1586 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.1587 + png_warning(png_ptr, 1.1588 + "libpng does not support gamma+background+rgb_to_gray"); 1.1589 + 1.1590 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.1591 + { 1.1592 + /* We don't get to here unless there is a tRNS chunk with non-opaque 1.1593 + * entries - see the checking code at the start of this function. 1.1594 + */ 1.1595 + png_color back, back_1; 1.1596 + png_colorp palette = png_ptr->palette; 1.1597 + int num_palette = png_ptr->num_palette; 1.1598 + int i; 1.1599 + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 1.1600 + { 1.1601 + 1.1602 + back.red = png_ptr->gamma_table[png_ptr->background.red]; 1.1603 + back.green = png_ptr->gamma_table[png_ptr->background.green]; 1.1604 + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 1.1605 + 1.1606 + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 1.1607 + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 1.1608 + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 1.1609 + } 1.1610 + else 1.1611 + { 1.1612 + png_fixed_point g, gs; 1.1613 + 1.1614 + switch (png_ptr->background_gamma_type) 1.1615 + { 1.1616 + case PNG_BACKGROUND_GAMMA_SCREEN: 1.1617 + g = (png_ptr->screen_gamma); 1.1618 + gs = PNG_FP_1; 1.1619 + break; 1.1620 + 1.1621 + case PNG_BACKGROUND_GAMMA_FILE: 1.1622 + g = png_reciprocal(png_ptr->colorspace.gamma); 1.1623 + gs = png_reciprocal2(png_ptr->colorspace.gamma, 1.1624 + png_ptr->screen_gamma); 1.1625 + break; 1.1626 + 1.1627 + case PNG_BACKGROUND_GAMMA_UNIQUE: 1.1628 + g = png_reciprocal(png_ptr->background_gamma); 1.1629 + gs = png_reciprocal2(png_ptr->background_gamma, 1.1630 + png_ptr->screen_gamma); 1.1631 + break; 1.1632 + default: 1.1633 + g = PNG_FP_1; /* back_1 */ 1.1634 + gs = PNG_FP_1; /* back */ 1.1635 + break; 1.1636 + } 1.1637 + 1.1638 + if (png_gamma_significant(gs)) 1.1639 + { 1.1640 + back.red = png_gamma_8bit_correct(png_ptr->background.red, 1.1641 + gs); 1.1642 + back.green = png_gamma_8bit_correct(png_ptr->background.green, 1.1643 + gs); 1.1644 + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, 1.1645 + gs); 1.1646 + } 1.1647 + 1.1648 + else 1.1649 + { 1.1650 + back.red = (png_byte)png_ptr->background.red; 1.1651 + back.green = (png_byte)png_ptr->background.green; 1.1652 + back.blue = (png_byte)png_ptr->background.blue; 1.1653 + } 1.1654 + 1.1655 + if (png_gamma_significant(g)) 1.1656 + { 1.1657 + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, 1.1658 + g); 1.1659 + back_1.green = png_gamma_8bit_correct( 1.1660 + png_ptr->background.green, g); 1.1661 + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, 1.1662 + g); 1.1663 + } 1.1664 + 1.1665 + else 1.1666 + { 1.1667 + back_1.red = (png_byte)png_ptr->background.red; 1.1668 + back_1.green = (png_byte)png_ptr->background.green; 1.1669 + back_1.blue = (png_byte)png_ptr->background.blue; 1.1670 + } 1.1671 + } 1.1672 + 1.1673 + for (i = 0; i < num_palette; i++) 1.1674 + { 1.1675 + if (i < (int)png_ptr->num_trans && 1.1676 + png_ptr->trans_alpha[i] != 0xff) 1.1677 + { 1.1678 + if (png_ptr->trans_alpha[i] == 0) 1.1679 + { 1.1680 + palette[i] = back; 1.1681 + } 1.1682 + else /* if (png_ptr->trans_alpha[i] != 0xff) */ 1.1683 + { 1.1684 + png_byte v, w; 1.1685 + 1.1686 + v = png_ptr->gamma_to_1[palette[i].red]; 1.1687 + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); 1.1688 + palette[i].red = png_ptr->gamma_from_1[w]; 1.1689 + 1.1690 + v = png_ptr->gamma_to_1[palette[i].green]; 1.1691 + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); 1.1692 + palette[i].green = png_ptr->gamma_from_1[w]; 1.1693 + 1.1694 + v = png_ptr->gamma_to_1[palette[i].blue]; 1.1695 + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); 1.1696 + palette[i].blue = png_ptr->gamma_from_1[w]; 1.1697 + } 1.1698 + } 1.1699 + else 1.1700 + { 1.1701 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.1702 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.1703 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.1704 + } 1.1705 + } 1.1706 + 1.1707 + /* Prevent the transformations being done again. 1.1708 + * 1.1709 + * NOTE: this is highly dubious; it removes the transformations in 1.1710 + * place. This seems inconsistent with the general treatment of the 1.1711 + * transformations elsewhere. 1.1712 + */ 1.1713 + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); 1.1714 + } /* color_type == PNG_COLOR_TYPE_PALETTE */ 1.1715 + 1.1716 + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 1.1717 + else /* color_type != PNG_COLOR_TYPE_PALETTE */ 1.1718 + { 1.1719 + int gs_sig, g_sig; 1.1720 + png_fixed_point g = PNG_FP_1; /* Correction to linear */ 1.1721 + png_fixed_point gs = PNG_FP_1; /* Correction to screen */ 1.1722 + 1.1723 + switch (png_ptr->background_gamma_type) 1.1724 + { 1.1725 + case PNG_BACKGROUND_GAMMA_SCREEN: 1.1726 + g = png_ptr->screen_gamma; 1.1727 + /* gs = PNG_FP_1; */ 1.1728 + break; 1.1729 + 1.1730 + case PNG_BACKGROUND_GAMMA_FILE: 1.1731 + g = png_reciprocal(png_ptr->colorspace.gamma); 1.1732 + gs = png_reciprocal2(png_ptr->colorspace.gamma, 1.1733 + png_ptr->screen_gamma); 1.1734 + break; 1.1735 + 1.1736 + case PNG_BACKGROUND_GAMMA_UNIQUE: 1.1737 + g = png_reciprocal(png_ptr->background_gamma); 1.1738 + gs = png_reciprocal2(png_ptr->background_gamma, 1.1739 + png_ptr->screen_gamma); 1.1740 + break; 1.1741 + 1.1742 + default: 1.1743 + png_error(png_ptr, "invalid background gamma type"); 1.1744 + } 1.1745 + 1.1746 + g_sig = png_gamma_significant(g); 1.1747 + gs_sig = png_gamma_significant(gs); 1.1748 + 1.1749 + if (g_sig) 1.1750 + png_ptr->background_1.gray = png_gamma_correct(png_ptr, 1.1751 + png_ptr->background.gray, g); 1.1752 + 1.1753 + if (gs_sig) 1.1754 + png_ptr->background.gray = png_gamma_correct(png_ptr, 1.1755 + png_ptr->background.gray, gs); 1.1756 + 1.1757 + if ((png_ptr->background.red != png_ptr->background.green) || 1.1758 + (png_ptr->background.red != png_ptr->background.blue) || 1.1759 + (png_ptr->background.red != png_ptr->background.gray)) 1.1760 + { 1.1761 + /* RGB or RGBA with color background */ 1.1762 + if (g_sig) 1.1763 + { 1.1764 + png_ptr->background_1.red = png_gamma_correct(png_ptr, 1.1765 + png_ptr->background.red, g); 1.1766 + 1.1767 + png_ptr->background_1.green = png_gamma_correct(png_ptr, 1.1768 + png_ptr->background.green, g); 1.1769 + 1.1770 + png_ptr->background_1.blue = png_gamma_correct(png_ptr, 1.1771 + png_ptr->background.blue, g); 1.1772 + } 1.1773 + 1.1774 + if (gs_sig) 1.1775 + { 1.1776 + png_ptr->background.red = png_gamma_correct(png_ptr, 1.1777 + png_ptr->background.red, gs); 1.1778 + 1.1779 + png_ptr->background.green = png_gamma_correct(png_ptr, 1.1780 + png_ptr->background.green, gs); 1.1781 + 1.1782 + png_ptr->background.blue = png_gamma_correct(png_ptr, 1.1783 + png_ptr->background.blue, gs); 1.1784 + } 1.1785 + } 1.1786 + 1.1787 + else 1.1788 + { 1.1789 + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 1.1790 + png_ptr->background_1.red = png_ptr->background_1.green 1.1791 + = png_ptr->background_1.blue = png_ptr->background_1.gray; 1.1792 + 1.1793 + png_ptr->background.red = png_ptr->background.green 1.1794 + = png_ptr->background.blue = png_ptr->background.gray; 1.1795 + } 1.1796 + 1.1797 + /* The background is now in screen gamma: */ 1.1798 + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; 1.1799 + } /* color_type != PNG_COLOR_TYPE_PALETTE */ 1.1800 + }/* png_ptr->transformations & PNG_BACKGROUND */ 1.1801 + 1.1802 + else 1.1803 + /* Transformation does not include PNG_BACKGROUND */ 1.1804 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1.1805 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE 1.1806 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.1807 + /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ 1.1808 + && ((png_ptr->transformations & PNG_EXPAND) == 0 || 1.1809 + (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) 1.1810 +#endif 1.1811 + ) 1.1812 + { 1.1813 + png_colorp palette = png_ptr->palette; 1.1814 + int num_palette = png_ptr->num_palette; 1.1815 + int i; 1.1816 + 1.1817 + /* NOTE: there are other transformations that should probably be in 1.1818 + * here too. 1.1819 + */ 1.1820 + for (i = 0; i < num_palette; i++) 1.1821 + { 1.1822 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.1823 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.1824 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.1825 + } 1.1826 + 1.1827 + /* Done the gamma correction. */ 1.1828 + png_ptr->transformations &= ~PNG_GAMMA; 1.1829 + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ 1.1830 + } 1.1831 +#ifdef PNG_READ_BACKGROUND_SUPPORTED 1.1832 + else 1.1833 +#endif 1.1834 +#endif /* PNG_READ_GAMMA_SUPPORTED */ 1.1835 + 1.1836 +#ifdef PNG_READ_BACKGROUND_SUPPORTED 1.1837 + /* No GAMMA transformation (see the hanging else 4 lines above) */ 1.1838 + if ((png_ptr->transformations & PNG_COMPOSE) && 1.1839 + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 1.1840 + { 1.1841 + int i; 1.1842 + int istop = (int)png_ptr->num_trans; 1.1843 + png_color back; 1.1844 + png_colorp palette = png_ptr->palette; 1.1845 + 1.1846 + back.red = (png_byte)png_ptr->background.red; 1.1847 + back.green = (png_byte)png_ptr->background.green; 1.1848 + back.blue = (png_byte)png_ptr->background.blue; 1.1849 + 1.1850 + for (i = 0; i < istop; i++) 1.1851 + { 1.1852 + if (png_ptr->trans_alpha[i] == 0) 1.1853 + { 1.1854 + palette[i] = back; 1.1855 + } 1.1856 + 1.1857 + else if (png_ptr->trans_alpha[i] != 0xff) 1.1858 + { 1.1859 + /* The png_composite() macro is defined in png.h */ 1.1860 + png_composite(palette[i].red, palette[i].red, 1.1861 + png_ptr->trans_alpha[i], back.red); 1.1862 + 1.1863 + png_composite(palette[i].green, palette[i].green, 1.1864 + png_ptr->trans_alpha[i], back.green); 1.1865 + 1.1866 + png_composite(palette[i].blue, palette[i].blue, 1.1867 + png_ptr->trans_alpha[i], back.blue); 1.1868 + } 1.1869 + } 1.1870 + 1.1871 + png_ptr->transformations &= ~PNG_COMPOSE; 1.1872 + } 1.1873 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1.1874 + 1.1875 +#ifdef PNG_READ_SHIFT_SUPPORTED 1.1876 + if ((png_ptr->transformations & PNG_SHIFT) && 1.1877 + !(png_ptr->transformations & PNG_EXPAND) && 1.1878 + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 1.1879 + { 1.1880 + int i; 1.1881 + int istop = png_ptr->num_palette; 1.1882 + int shift = 8 - png_ptr->sig_bit.red; 1.1883 + 1.1884 + png_ptr->transformations &= ~PNG_SHIFT; 1.1885 + 1.1886 + /* significant bits can be in the range 1 to 7 for a meaninful result, if 1.1887 + * the number of significant bits is 0 then no shift is done (this is an 1.1888 + * error condition which is silently ignored.) 1.1889 + */ 1.1890 + if (shift > 0 && shift < 8) 1.1891 + for (i=0; i<istop; ++i) 1.1892 + { 1.1893 + int component = png_ptr->palette[i].red; 1.1894 + 1.1895 + component >>= shift; 1.1896 + png_ptr->palette[i].red = (png_byte)component; 1.1897 + } 1.1898 + 1.1899 + shift = 8 - png_ptr->sig_bit.green; 1.1900 + if (shift > 0 && shift < 8) 1.1901 + for (i=0; i<istop; ++i) 1.1902 + { 1.1903 + int component = png_ptr->palette[i].green; 1.1904 + 1.1905 + component >>= shift; 1.1906 + png_ptr->palette[i].green = (png_byte)component; 1.1907 + } 1.1908 + 1.1909 + shift = 8 - png_ptr->sig_bit.blue; 1.1910 + if (shift > 0 && shift < 8) 1.1911 + for (i=0; i<istop; ++i) 1.1912 + { 1.1913 + int component = png_ptr->palette[i].blue; 1.1914 + 1.1915 + component >>= shift; 1.1916 + png_ptr->palette[i].blue = (png_byte)component; 1.1917 + } 1.1918 + } 1.1919 +#endif /* PNG_READ_SHIFT_SUPPORTED */ 1.1920 +} 1.1921 + 1.1922 +/* Modify the info structure to reflect the transformations. The 1.1923 + * info should be updated so a PNG file could be written with it, 1.1924 + * assuming the transformations result in valid PNG data. 1.1925 + */ 1.1926 +void /* PRIVATE */ 1.1927 +png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) 1.1928 +{ 1.1929 + png_debug(1, "in png_read_transform_info"); 1.1930 + 1.1931 +#ifdef PNG_READ_EXPAND_SUPPORTED 1.1932 + if (png_ptr->transformations & PNG_EXPAND) 1.1933 + { 1.1934 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.1935 + { 1.1936 + /* This check must match what actually happens in 1.1937 + * png_do_expand_palette; if it ever checks the tRNS chunk to see if 1.1938 + * it is all opaque we must do the same (at present it does not.) 1.1939 + */ 1.1940 + if (png_ptr->num_trans > 0) 1.1941 + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1.1942 + 1.1943 + else 1.1944 + info_ptr->color_type = PNG_COLOR_TYPE_RGB; 1.1945 + 1.1946 + info_ptr->bit_depth = 8; 1.1947 + info_ptr->num_trans = 0; 1.1948 + 1.1949 + if (png_ptr->palette == NULL) 1.1950 + png_error (png_ptr, "Palette is NULL in indexed image"); 1.1951 + } 1.1952 + else 1.1953 + { 1.1954 + if (png_ptr->num_trans) 1.1955 + { 1.1956 + if (png_ptr->transformations & PNG_EXPAND_tRNS) 1.1957 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1.1958 + } 1.1959 + if (info_ptr->bit_depth < 8) 1.1960 + info_ptr->bit_depth = 8; 1.1961 + 1.1962 + info_ptr->num_trans = 0; 1.1963 + } 1.1964 + } 1.1965 +#endif 1.1966 + 1.1967 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 1.1968 + defined(PNG_READ_ALPHA_MODE_SUPPORTED) 1.1969 + /* The following is almost certainly wrong unless the background value is in 1.1970 + * the screen space! 1.1971 + */ 1.1972 + if (png_ptr->transformations & PNG_COMPOSE) 1.1973 + info_ptr->background = png_ptr->background; 1.1974 +#endif 1.1975 + 1.1976 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.1977 + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), 1.1978 + * however it seems that the code in png_init_read_transformations, which has 1.1979 + * been called before this from png_read_update_info->png_read_start_row 1.1980 + * sometimes does the gamma transform and cancels the flag. 1.1981 + * 1.1982 + * TODO: this looks wrong; the info_ptr should end up with a gamma equal to 1.1983 + * the screen_gamma value. The following probably results in weirdness if 1.1984 + * the info_ptr is used by the app after the rows have been read. 1.1985 + */ 1.1986 + info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; 1.1987 +#endif 1.1988 + 1.1989 + if (info_ptr->bit_depth == 16) 1.1990 + { 1.1991 +# ifdef PNG_READ_16BIT_SUPPORTED 1.1992 +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1.1993 + if (png_ptr->transformations & PNG_SCALE_16_TO_8) 1.1994 + info_ptr->bit_depth = 8; 1.1995 +# endif 1.1996 + 1.1997 +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1.1998 + if (png_ptr->transformations & PNG_16_TO_8) 1.1999 + info_ptr->bit_depth = 8; 1.2000 +# endif 1.2001 + 1.2002 +# else 1.2003 + /* No 16 bit support: force chopping 16-bit input down to 8, in this case 1.2004 + * the app program can chose if both APIs are available by setting the 1.2005 + * correct scaling to use. 1.2006 + */ 1.2007 +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1.2008 + /* For compatibility with previous versions use the strip method by 1.2009 + * default. This code works because if PNG_SCALE_16_TO_8 is already 1.2010 + * set the code below will do that in preference to the chop. 1.2011 + */ 1.2012 + png_ptr->transformations |= PNG_16_TO_8; 1.2013 + info_ptr->bit_depth = 8; 1.2014 +# else 1.2015 + 1.2016 +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1.2017 + png_ptr->transformations |= PNG_SCALE_16_TO_8; 1.2018 + info_ptr->bit_depth = 8; 1.2019 +# else 1.2020 + 1.2021 + CONFIGURATION ERROR: you must enable at least one 16 to 8 method 1.2022 +# endif 1.2023 +# endif 1.2024 +#endif /* !READ_16BIT_SUPPORTED */ 1.2025 + } 1.2026 + 1.2027 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.2028 + if (png_ptr->transformations & PNG_GRAY_TO_RGB) 1.2029 + info_ptr->color_type = (png_byte)(info_ptr->color_type | 1.2030 + PNG_COLOR_MASK_COLOR); 1.2031 +#endif 1.2032 + 1.2033 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.2034 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.2035 + info_ptr->color_type = (png_byte)(info_ptr->color_type & 1.2036 + ~PNG_COLOR_MASK_COLOR); 1.2037 +#endif 1.2038 + 1.2039 +#ifdef PNG_READ_QUANTIZE_SUPPORTED 1.2040 + if (png_ptr->transformations & PNG_QUANTIZE) 1.2041 + { 1.2042 + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1.2043 + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 1.2044 + png_ptr->palette_lookup && info_ptr->bit_depth == 8) 1.2045 + { 1.2046 + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 1.2047 + } 1.2048 + } 1.2049 +#endif 1.2050 + 1.2051 +#ifdef PNG_READ_EXPAND_16_SUPPORTED 1.2052 + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && 1.2053 + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) 1.2054 + { 1.2055 + info_ptr->bit_depth = 16; 1.2056 + } 1.2057 +#endif 1.2058 + 1.2059 +#ifdef PNG_READ_PACK_SUPPORTED 1.2060 + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) 1.2061 + info_ptr->bit_depth = 8; 1.2062 +#endif 1.2063 + 1.2064 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.2065 + info_ptr->channels = 1; 1.2066 + 1.2067 + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 1.2068 + info_ptr->channels = 3; 1.2069 + 1.2070 + else 1.2071 + info_ptr->channels = 1; 1.2072 + 1.2073 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1.2074 + if (png_ptr->transformations & PNG_STRIP_ALPHA) 1.2075 + { 1.2076 + info_ptr->color_type = (png_byte)(info_ptr->color_type & 1.2077 + ~PNG_COLOR_MASK_ALPHA); 1.2078 + info_ptr->num_trans = 0; 1.2079 + } 1.2080 +#endif 1.2081 + 1.2082 + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 1.2083 + info_ptr->channels++; 1.2084 + 1.2085 +#ifdef PNG_READ_FILLER_SUPPORTED 1.2086 + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 1.2087 + if ((png_ptr->transformations & PNG_FILLER) && 1.2088 + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1.2089 + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) 1.2090 + { 1.2091 + info_ptr->channels++; 1.2092 + /* If adding a true alpha channel not just filler */ 1.2093 + if (png_ptr->transformations & PNG_ADD_ALPHA) 1.2094 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1.2095 + } 1.2096 +#endif 1.2097 + 1.2098 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 1.2099 +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 1.2100 + if (png_ptr->transformations & PNG_USER_TRANSFORM) 1.2101 + { 1.2102 + if (info_ptr->bit_depth < png_ptr->user_transform_depth) 1.2103 + info_ptr->bit_depth = png_ptr->user_transform_depth; 1.2104 + 1.2105 + if (info_ptr->channels < png_ptr->user_transform_channels) 1.2106 + info_ptr->channels = png_ptr->user_transform_channels; 1.2107 + } 1.2108 +#endif 1.2109 + 1.2110 + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 1.2111 + info_ptr->bit_depth); 1.2112 + 1.2113 + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 1.2114 + 1.2115 + /* Adding in 1.5.4: cache the above value in png_struct so that we can later 1.2116 + * check in png_rowbytes that the user buffer won't get overwritten. Note 1.2117 + * that the field is not always set - if png_read_update_info isn't called 1.2118 + * the application has to either not do any transforms or get the calculation 1.2119 + * right itself. 1.2120 + */ 1.2121 + png_ptr->info_rowbytes = info_ptr->rowbytes; 1.2122 + 1.2123 +#ifndef PNG_READ_EXPAND_SUPPORTED 1.2124 + if (png_ptr) 1.2125 + return; 1.2126 +#endif 1.2127 +} 1.2128 + 1.2129 +#ifdef PNG_READ_PACK_SUPPORTED 1.2130 +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 1.2131 + * without changing the actual values. Thus, if you had a row with 1.2132 + * a bit depth of 1, you would end up with bytes that only contained 1.2133 + * the numbers 0 or 1. If you would rather they contain 0 and 255, use 1.2134 + * png_do_shift() after this. 1.2135 + */ 1.2136 +static void 1.2137 +png_do_unpack(png_row_infop row_info, png_bytep row) 1.2138 +{ 1.2139 + png_debug(1, "in png_do_unpack"); 1.2140 + 1.2141 + if (row_info->bit_depth < 8) 1.2142 + { 1.2143 + png_uint_32 i; 1.2144 + png_uint_32 row_width=row_info->width; 1.2145 + 1.2146 + switch (row_info->bit_depth) 1.2147 + { 1.2148 + case 1: 1.2149 + { 1.2150 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 1.2151 + png_bytep dp = row + (png_size_t)row_width - 1; 1.2152 + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); 1.2153 + for (i = 0; i < row_width; i++) 1.2154 + { 1.2155 + *dp = (png_byte)((*sp >> shift) & 0x01); 1.2156 + 1.2157 + if (shift == 7) 1.2158 + { 1.2159 + shift = 0; 1.2160 + sp--; 1.2161 + } 1.2162 + 1.2163 + else 1.2164 + shift++; 1.2165 + 1.2166 + dp--; 1.2167 + } 1.2168 + break; 1.2169 + } 1.2170 + 1.2171 + case 2: 1.2172 + { 1.2173 + 1.2174 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 1.2175 + png_bytep dp = row + (png_size_t)row_width - 1; 1.2176 + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.2177 + for (i = 0; i < row_width; i++) 1.2178 + { 1.2179 + *dp = (png_byte)((*sp >> shift) & 0x03); 1.2180 + 1.2181 + if (shift == 6) 1.2182 + { 1.2183 + shift = 0; 1.2184 + sp--; 1.2185 + } 1.2186 + 1.2187 + else 1.2188 + shift += 2; 1.2189 + 1.2190 + dp--; 1.2191 + } 1.2192 + break; 1.2193 + } 1.2194 + 1.2195 + case 4: 1.2196 + { 1.2197 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 1.2198 + png_bytep dp = row + (png_size_t)row_width - 1; 1.2199 + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 1.2200 + for (i = 0; i < row_width; i++) 1.2201 + { 1.2202 + *dp = (png_byte)((*sp >> shift) & 0x0f); 1.2203 + 1.2204 + if (shift == 4) 1.2205 + { 1.2206 + shift = 0; 1.2207 + sp--; 1.2208 + } 1.2209 + 1.2210 + else 1.2211 + shift = 4; 1.2212 + 1.2213 + dp--; 1.2214 + } 1.2215 + break; 1.2216 + } 1.2217 + 1.2218 + default: 1.2219 + break; 1.2220 + } 1.2221 + row_info->bit_depth = 8; 1.2222 + row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1.2223 + row_info->rowbytes = row_width * row_info->channels; 1.2224 + } 1.2225 +} 1.2226 +#endif 1.2227 + 1.2228 +#ifdef PNG_READ_SHIFT_SUPPORTED 1.2229 +/* Reverse the effects of png_do_shift. This routine merely shifts the 1.2230 + * pixels back to their significant bits values. Thus, if you have 1.2231 + * a row of bit depth 8, but only 5 are significant, this will shift 1.2232 + * the values back to 0 through 31. 1.2233 + */ 1.2234 +static void 1.2235 +png_do_unshift(png_row_infop row_info, png_bytep row, 1.2236 + png_const_color_8p sig_bits) 1.2237 +{ 1.2238 + int color_type; 1.2239 + 1.2240 + png_debug(1, "in png_do_unshift"); 1.2241 + 1.2242 + /* The palette case has already been handled in the _init routine. */ 1.2243 + color_type = row_info->color_type; 1.2244 + 1.2245 + if (color_type != PNG_COLOR_TYPE_PALETTE) 1.2246 + { 1.2247 + int shift[4]; 1.2248 + int channels = 0; 1.2249 + int bit_depth = row_info->bit_depth; 1.2250 + 1.2251 + if (color_type & PNG_COLOR_MASK_COLOR) 1.2252 + { 1.2253 + shift[channels++] = bit_depth - sig_bits->red; 1.2254 + shift[channels++] = bit_depth - sig_bits->green; 1.2255 + shift[channels++] = bit_depth - sig_bits->blue; 1.2256 + } 1.2257 + 1.2258 + else 1.2259 + { 1.2260 + shift[channels++] = bit_depth - sig_bits->gray; 1.2261 + } 1.2262 + 1.2263 + if (color_type & PNG_COLOR_MASK_ALPHA) 1.2264 + { 1.2265 + shift[channels++] = bit_depth - sig_bits->alpha; 1.2266 + } 1.2267 + 1.2268 + { 1.2269 + int c, have_shift; 1.2270 + 1.2271 + for (c = have_shift = 0; c < channels; ++c) 1.2272 + { 1.2273 + /* A shift of more than the bit depth is an error condition but it 1.2274 + * gets ignored here. 1.2275 + */ 1.2276 + if (shift[c] <= 0 || shift[c] >= bit_depth) 1.2277 + shift[c] = 0; 1.2278 + 1.2279 + else 1.2280 + have_shift = 1; 1.2281 + } 1.2282 + 1.2283 + if (!have_shift) 1.2284 + return; 1.2285 + } 1.2286 + 1.2287 + switch (bit_depth) 1.2288 + { 1.2289 + default: 1.2290 + /* Must be 1bpp gray: should not be here! */ 1.2291 + /* NOTREACHED */ 1.2292 + break; 1.2293 + 1.2294 + case 2: 1.2295 + /* Must be 2bpp gray */ 1.2296 + /* assert(channels == 1 && shift[0] == 1) */ 1.2297 + { 1.2298 + png_bytep bp = row; 1.2299 + png_bytep bp_end = bp + row_info->rowbytes; 1.2300 + 1.2301 + while (bp < bp_end) 1.2302 + { 1.2303 + int b = (*bp >> 1) & 0x55; 1.2304 + *bp++ = (png_byte)b; 1.2305 + } 1.2306 + break; 1.2307 + } 1.2308 + 1.2309 + case 4: 1.2310 + /* Must be 4bpp gray */ 1.2311 + /* assert(channels == 1) */ 1.2312 + { 1.2313 + png_bytep bp = row; 1.2314 + png_bytep bp_end = bp + row_info->rowbytes; 1.2315 + int gray_shift = shift[0]; 1.2316 + int mask = 0xf >> gray_shift; 1.2317 + 1.2318 + mask |= mask << 4; 1.2319 + 1.2320 + while (bp < bp_end) 1.2321 + { 1.2322 + int b = (*bp >> gray_shift) & mask; 1.2323 + *bp++ = (png_byte)b; 1.2324 + } 1.2325 + break; 1.2326 + } 1.2327 + 1.2328 + case 8: 1.2329 + /* Single byte components, G, GA, RGB, RGBA */ 1.2330 + { 1.2331 + png_bytep bp = row; 1.2332 + png_bytep bp_end = bp + row_info->rowbytes; 1.2333 + int channel = 0; 1.2334 + 1.2335 + while (bp < bp_end) 1.2336 + { 1.2337 + int b = *bp >> shift[channel]; 1.2338 + if (++channel >= channels) 1.2339 + channel = 0; 1.2340 + *bp++ = (png_byte)b; 1.2341 + } 1.2342 + break; 1.2343 + } 1.2344 + 1.2345 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2346 + case 16: 1.2347 + /* Double byte components, G, GA, RGB, RGBA */ 1.2348 + { 1.2349 + png_bytep bp = row; 1.2350 + png_bytep bp_end = bp + row_info->rowbytes; 1.2351 + int channel = 0; 1.2352 + 1.2353 + while (bp < bp_end) 1.2354 + { 1.2355 + int value = (bp[0] << 8) + bp[1]; 1.2356 + 1.2357 + value >>= shift[channel]; 1.2358 + if (++channel >= channels) 1.2359 + channel = 0; 1.2360 + *bp++ = (png_byte)(value >> 8); 1.2361 + *bp++ = (png_byte)(value & 0xff); 1.2362 + } 1.2363 + break; 1.2364 + } 1.2365 +#endif 1.2366 + } 1.2367 + } 1.2368 +} 1.2369 +#endif 1.2370 + 1.2371 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1.2372 +/* Scale rows of bit depth 16 down to 8 accurately */ 1.2373 +static void 1.2374 +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) 1.2375 +{ 1.2376 + png_debug(1, "in png_do_scale_16_to_8"); 1.2377 + 1.2378 + if (row_info->bit_depth == 16) 1.2379 + { 1.2380 + png_bytep sp = row; /* source */ 1.2381 + png_bytep dp = row; /* destination */ 1.2382 + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 1.2383 + 1.2384 + while (sp < ep) 1.2385 + { 1.2386 + /* The input is an array of 16 bit components, these must be scaled to 1.2387 + * 8 bits each. For a 16 bit value V the required value (from the PNG 1.2388 + * specification) is: 1.2389 + * 1.2390 + * (V * 255) / 65535 1.2391 + * 1.2392 + * This reduces to round(V / 257), or floor((V + 128.5)/257) 1.2393 + * 1.2394 + * Represent V as the two byte value vhi.vlo. Make a guess that the 1.2395 + * result is the top byte of V, vhi, then the correction to this value 1.2396 + * is: 1.2397 + * 1.2398 + * error = floor(((V-vhi.vhi) + 128.5) / 257) 1.2399 + * = floor(((vlo-vhi) + 128.5) / 257) 1.2400 + * 1.2401 + * This can be approximated using integer arithmetic (and a signed 1.2402 + * shift): 1.2403 + * 1.2404 + * error = (vlo-vhi+128) >> 8; 1.2405 + * 1.2406 + * The approximate differs from the exact answer only when (vlo-vhi) is 1.2407 + * 128; it then gives a correction of +1 when the exact correction is 1.2408 + * 0. This gives 128 errors. The exact answer (correct for all 16 bit 1.2409 + * input values) is: 1.2410 + * 1.2411 + * error = (vlo-vhi+128)*65535 >> 24; 1.2412 + * 1.2413 + * An alternative arithmetic calculation which also gives no errors is: 1.2414 + * 1.2415 + * (V * 255 + 32895) >> 16 1.2416 + */ 1.2417 + 1.2418 + png_int_32 tmp = *sp++; /* must be signed! */ 1.2419 + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; 1.2420 + *dp++ = (png_byte)tmp; 1.2421 + } 1.2422 + 1.2423 + row_info->bit_depth = 8; 1.2424 + row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1.2425 + row_info->rowbytes = row_info->width * row_info->channels; 1.2426 + } 1.2427 +} 1.2428 +#endif 1.2429 + 1.2430 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1.2431 +static void 1.2432 +/* Simply discard the low byte. This was the default behavior prior 1.2433 + * to libpng-1.5.4. 1.2434 + */ 1.2435 +png_do_chop(png_row_infop row_info, png_bytep row) 1.2436 +{ 1.2437 + png_debug(1, "in png_do_chop"); 1.2438 + 1.2439 + if (row_info->bit_depth == 16) 1.2440 + { 1.2441 + png_bytep sp = row; /* source */ 1.2442 + png_bytep dp = row; /* destination */ 1.2443 + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 1.2444 + 1.2445 + while (sp < ep) 1.2446 + { 1.2447 + *dp++ = *sp; 1.2448 + sp += 2; /* skip low byte */ 1.2449 + } 1.2450 + 1.2451 + row_info->bit_depth = 8; 1.2452 + row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1.2453 + row_info->rowbytes = row_info->width * row_info->channels; 1.2454 + } 1.2455 +} 1.2456 +#endif 1.2457 + 1.2458 +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1.2459 +static void 1.2460 +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 1.2461 +{ 1.2462 + png_debug(1, "in png_do_read_swap_alpha"); 1.2463 + 1.2464 + { 1.2465 + png_uint_32 row_width = row_info->width; 1.2466 + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.2467 + { 1.2468 + /* This converts from RGBA to ARGB */ 1.2469 + if (row_info->bit_depth == 8) 1.2470 + { 1.2471 + png_bytep sp = row + row_info->rowbytes; 1.2472 + png_bytep dp = sp; 1.2473 + png_byte save; 1.2474 + png_uint_32 i; 1.2475 + 1.2476 + for (i = 0; i < row_width; i++) 1.2477 + { 1.2478 + save = *(--sp); 1.2479 + *(--dp) = *(--sp); 1.2480 + *(--dp) = *(--sp); 1.2481 + *(--dp) = *(--sp); 1.2482 + *(--dp) = save; 1.2483 + } 1.2484 + } 1.2485 + 1.2486 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2487 + /* This converts from RRGGBBAA to AARRGGBB */ 1.2488 + else 1.2489 + { 1.2490 + png_bytep sp = row + row_info->rowbytes; 1.2491 + png_bytep dp = sp; 1.2492 + png_byte save[2]; 1.2493 + png_uint_32 i; 1.2494 + 1.2495 + for (i = 0; i < row_width; i++) 1.2496 + { 1.2497 + save[0] = *(--sp); 1.2498 + save[1] = *(--sp); 1.2499 + *(--dp) = *(--sp); 1.2500 + *(--dp) = *(--sp); 1.2501 + *(--dp) = *(--sp); 1.2502 + *(--dp) = *(--sp); 1.2503 + *(--dp) = *(--sp); 1.2504 + *(--dp) = *(--sp); 1.2505 + *(--dp) = save[0]; 1.2506 + *(--dp) = save[1]; 1.2507 + } 1.2508 + } 1.2509 +#endif 1.2510 + } 1.2511 + 1.2512 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.2513 + { 1.2514 + /* This converts from GA to AG */ 1.2515 + if (row_info->bit_depth == 8) 1.2516 + { 1.2517 + png_bytep sp = row + row_info->rowbytes; 1.2518 + png_bytep dp = sp; 1.2519 + png_byte save; 1.2520 + png_uint_32 i; 1.2521 + 1.2522 + for (i = 0; i < row_width; i++) 1.2523 + { 1.2524 + save = *(--sp); 1.2525 + *(--dp) = *(--sp); 1.2526 + *(--dp) = save; 1.2527 + } 1.2528 + } 1.2529 + 1.2530 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2531 + /* This converts from GGAA to AAGG */ 1.2532 + else 1.2533 + { 1.2534 + png_bytep sp = row + row_info->rowbytes; 1.2535 + png_bytep dp = sp; 1.2536 + png_byte save[2]; 1.2537 + png_uint_32 i; 1.2538 + 1.2539 + for (i = 0; i < row_width; i++) 1.2540 + { 1.2541 + save[0] = *(--sp); 1.2542 + save[1] = *(--sp); 1.2543 + *(--dp) = *(--sp); 1.2544 + *(--dp) = *(--sp); 1.2545 + *(--dp) = save[0]; 1.2546 + *(--dp) = save[1]; 1.2547 + } 1.2548 + } 1.2549 +#endif 1.2550 + } 1.2551 + } 1.2552 +} 1.2553 +#endif 1.2554 + 1.2555 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1.2556 +static void 1.2557 +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 1.2558 +{ 1.2559 + png_uint_32 row_width; 1.2560 + png_debug(1, "in png_do_read_invert_alpha"); 1.2561 + 1.2562 + row_width = row_info->width; 1.2563 + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.2564 + { 1.2565 + if (row_info->bit_depth == 8) 1.2566 + { 1.2567 + /* This inverts the alpha channel in RGBA */ 1.2568 + png_bytep sp = row + row_info->rowbytes; 1.2569 + png_bytep dp = sp; 1.2570 + png_uint_32 i; 1.2571 + 1.2572 + for (i = 0; i < row_width; i++) 1.2573 + { 1.2574 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2575 + 1.2576 +/* This does nothing: 1.2577 + *(--dp) = *(--sp); 1.2578 + *(--dp) = *(--sp); 1.2579 + *(--dp) = *(--sp); 1.2580 + We can replace it with: 1.2581 +*/ 1.2582 + sp-=3; 1.2583 + dp=sp; 1.2584 + } 1.2585 + } 1.2586 + 1.2587 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2588 + /* This inverts the alpha channel in RRGGBBAA */ 1.2589 + else 1.2590 + { 1.2591 + png_bytep sp = row + row_info->rowbytes; 1.2592 + png_bytep dp = sp; 1.2593 + png_uint_32 i; 1.2594 + 1.2595 + for (i = 0; i < row_width; i++) 1.2596 + { 1.2597 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2598 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2599 + 1.2600 +/* This does nothing: 1.2601 + *(--dp) = *(--sp); 1.2602 + *(--dp) = *(--sp); 1.2603 + *(--dp) = *(--sp); 1.2604 + *(--dp) = *(--sp); 1.2605 + *(--dp) = *(--sp); 1.2606 + *(--dp) = *(--sp); 1.2607 + We can replace it with: 1.2608 +*/ 1.2609 + sp-=6; 1.2610 + dp=sp; 1.2611 + } 1.2612 + } 1.2613 +#endif 1.2614 + } 1.2615 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.2616 + { 1.2617 + if (row_info->bit_depth == 8) 1.2618 + { 1.2619 + /* This inverts the alpha channel in GA */ 1.2620 + png_bytep sp = row + row_info->rowbytes; 1.2621 + png_bytep dp = sp; 1.2622 + png_uint_32 i; 1.2623 + 1.2624 + for (i = 0; i < row_width; i++) 1.2625 + { 1.2626 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2627 + *(--dp) = *(--sp); 1.2628 + } 1.2629 + } 1.2630 + 1.2631 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2632 + else 1.2633 + { 1.2634 + /* This inverts the alpha channel in GGAA */ 1.2635 + png_bytep sp = row + row_info->rowbytes; 1.2636 + png_bytep dp = sp; 1.2637 + png_uint_32 i; 1.2638 + 1.2639 + for (i = 0; i < row_width; i++) 1.2640 + { 1.2641 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2642 + *(--dp) = (png_byte)(255 - *(--sp)); 1.2643 +/* 1.2644 + *(--dp) = *(--sp); 1.2645 + *(--dp) = *(--sp); 1.2646 +*/ 1.2647 + sp-=2; 1.2648 + dp=sp; 1.2649 + } 1.2650 + } 1.2651 +#endif 1.2652 + } 1.2653 +} 1.2654 +#endif 1.2655 + 1.2656 +#ifdef PNG_READ_FILLER_SUPPORTED 1.2657 +/* Add filler channel if we have RGB color */ 1.2658 +static void 1.2659 +png_do_read_filler(png_row_infop row_info, png_bytep row, 1.2660 + png_uint_32 filler, png_uint_32 flags) 1.2661 +{ 1.2662 + png_uint_32 i; 1.2663 + png_uint_32 row_width = row_info->width; 1.2664 + 1.2665 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2666 + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); 1.2667 +#endif 1.2668 + png_byte lo_filler = (png_byte)(filler & 0xff); 1.2669 + 1.2670 + png_debug(1, "in png_do_read_filler"); 1.2671 + 1.2672 + if ( 1.2673 + row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.2674 + { 1.2675 + if (row_info->bit_depth == 8) 1.2676 + { 1.2677 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2678 + { 1.2679 + /* This changes the data from G to GX */ 1.2680 + png_bytep sp = row + (png_size_t)row_width; 1.2681 + png_bytep dp = sp + (png_size_t)row_width; 1.2682 + for (i = 1; i < row_width; i++) 1.2683 + { 1.2684 + *(--dp) = lo_filler; 1.2685 + *(--dp) = *(--sp); 1.2686 + } 1.2687 + *(--dp) = lo_filler; 1.2688 + row_info->channels = 2; 1.2689 + row_info->pixel_depth = 16; 1.2690 + row_info->rowbytes = row_width * 2; 1.2691 + } 1.2692 + 1.2693 + else 1.2694 + { 1.2695 + /* This changes the data from G to XG */ 1.2696 + png_bytep sp = row + (png_size_t)row_width; 1.2697 + png_bytep dp = sp + (png_size_t)row_width; 1.2698 + for (i = 0; i < row_width; i++) 1.2699 + { 1.2700 + *(--dp) = *(--sp); 1.2701 + *(--dp) = lo_filler; 1.2702 + } 1.2703 + row_info->channels = 2; 1.2704 + row_info->pixel_depth = 16; 1.2705 + row_info->rowbytes = row_width * 2; 1.2706 + } 1.2707 + } 1.2708 + 1.2709 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2710 + else if (row_info->bit_depth == 16) 1.2711 + { 1.2712 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2713 + { 1.2714 + /* This changes the data from GG to GGXX */ 1.2715 + png_bytep sp = row + (png_size_t)row_width * 2; 1.2716 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2717 + for (i = 1; i < row_width; i++) 1.2718 + { 1.2719 + *(--dp) = hi_filler; 1.2720 + *(--dp) = lo_filler; 1.2721 + *(--dp) = *(--sp); 1.2722 + *(--dp) = *(--sp); 1.2723 + } 1.2724 + *(--dp) = hi_filler; 1.2725 + *(--dp) = lo_filler; 1.2726 + row_info->channels = 2; 1.2727 + row_info->pixel_depth = 32; 1.2728 + row_info->rowbytes = row_width * 4; 1.2729 + } 1.2730 + 1.2731 + else 1.2732 + { 1.2733 + /* This changes the data from GG to XXGG */ 1.2734 + png_bytep sp = row + (png_size_t)row_width * 2; 1.2735 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2736 + for (i = 0; i < row_width; i++) 1.2737 + { 1.2738 + *(--dp) = *(--sp); 1.2739 + *(--dp) = *(--sp); 1.2740 + *(--dp) = hi_filler; 1.2741 + *(--dp) = lo_filler; 1.2742 + } 1.2743 + row_info->channels = 2; 1.2744 + row_info->pixel_depth = 32; 1.2745 + row_info->rowbytes = row_width * 4; 1.2746 + } 1.2747 + } 1.2748 +#endif 1.2749 + } /* COLOR_TYPE == GRAY */ 1.2750 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 1.2751 + { 1.2752 + if (row_info->bit_depth == 8) 1.2753 + { 1.2754 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2755 + { 1.2756 + /* This changes the data from RGB to RGBX */ 1.2757 + png_bytep sp = row + (png_size_t)row_width * 3; 1.2758 + png_bytep dp = sp + (png_size_t)row_width; 1.2759 + for (i = 1; i < row_width; i++) 1.2760 + { 1.2761 + *(--dp) = lo_filler; 1.2762 + *(--dp) = *(--sp); 1.2763 + *(--dp) = *(--sp); 1.2764 + *(--dp) = *(--sp); 1.2765 + } 1.2766 + *(--dp) = lo_filler; 1.2767 + row_info->channels = 4; 1.2768 + row_info->pixel_depth = 32; 1.2769 + row_info->rowbytes = row_width * 4; 1.2770 + } 1.2771 + 1.2772 + else 1.2773 + { 1.2774 + /* This changes the data from RGB to XRGB */ 1.2775 + png_bytep sp = row + (png_size_t)row_width * 3; 1.2776 + png_bytep dp = sp + (png_size_t)row_width; 1.2777 + for (i = 0; i < row_width; i++) 1.2778 + { 1.2779 + *(--dp) = *(--sp); 1.2780 + *(--dp) = *(--sp); 1.2781 + *(--dp) = *(--sp); 1.2782 + *(--dp) = lo_filler; 1.2783 + } 1.2784 + row_info->channels = 4; 1.2785 + row_info->pixel_depth = 32; 1.2786 + row_info->rowbytes = row_width * 4; 1.2787 + } 1.2788 + } 1.2789 + 1.2790 +#ifdef PNG_READ_16BIT_SUPPORTED 1.2791 + else if (row_info->bit_depth == 16) 1.2792 + { 1.2793 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2794 + { 1.2795 + /* This changes the data from RRGGBB to RRGGBBXX */ 1.2796 + png_bytep sp = row + (png_size_t)row_width * 6; 1.2797 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2798 + for (i = 1; i < row_width; i++) 1.2799 + { 1.2800 + *(--dp) = hi_filler; 1.2801 + *(--dp) = lo_filler; 1.2802 + *(--dp) = *(--sp); 1.2803 + *(--dp) = *(--sp); 1.2804 + *(--dp) = *(--sp); 1.2805 + *(--dp) = *(--sp); 1.2806 + *(--dp) = *(--sp); 1.2807 + *(--dp) = *(--sp); 1.2808 + } 1.2809 + *(--dp) = hi_filler; 1.2810 + *(--dp) = lo_filler; 1.2811 + row_info->channels = 4; 1.2812 + row_info->pixel_depth = 64; 1.2813 + row_info->rowbytes = row_width * 8; 1.2814 + } 1.2815 + 1.2816 + else 1.2817 + { 1.2818 + /* This changes the data from RRGGBB to XXRRGGBB */ 1.2819 + png_bytep sp = row + (png_size_t)row_width * 6; 1.2820 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2821 + for (i = 0; i < row_width; i++) 1.2822 + { 1.2823 + *(--dp) = *(--sp); 1.2824 + *(--dp) = *(--sp); 1.2825 + *(--dp) = *(--sp); 1.2826 + *(--dp) = *(--sp); 1.2827 + *(--dp) = *(--sp); 1.2828 + *(--dp) = *(--sp); 1.2829 + *(--dp) = hi_filler; 1.2830 + *(--dp) = lo_filler; 1.2831 + } 1.2832 + 1.2833 + row_info->channels = 4; 1.2834 + row_info->pixel_depth = 64; 1.2835 + row_info->rowbytes = row_width * 8; 1.2836 + } 1.2837 + } 1.2838 +#endif 1.2839 + } /* COLOR_TYPE == RGB */ 1.2840 +} 1.2841 +#endif 1.2842 + 1.2843 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.2844 +/* Expand grayscale files to RGB, with or without alpha */ 1.2845 +static void 1.2846 +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 1.2847 +{ 1.2848 + png_uint_32 i; 1.2849 + png_uint_32 row_width = row_info->width; 1.2850 + 1.2851 + png_debug(1, "in png_do_gray_to_rgb"); 1.2852 + 1.2853 + if (row_info->bit_depth >= 8 && 1.2854 + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) 1.2855 + { 1.2856 + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.2857 + { 1.2858 + if (row_info->bit_depth == 8) 1.2859 + { 1.2860 + /* This changes G to RGB */ 1.2861 + png_bytep sp = row + (png_size_t)row_width - 1; 1.2862 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2863 + for (i = 0; i < row_width; i++) 1.2864 + { 1.2865 + *(dp--) = *sp; 1.2866 + *(dp--) = *sp; 1.2867 + *(dp--) = *(sp--); 1.2868 + } 1.2869 + } 1.2870 + 1.2871 + else 1.2872 + { 1.2873 + /* This changes GG to RRGGBB */ 1.2874 + png_bytep sp = row + (png_size_t)row_width * 2 - 1; 1.2875 + png_bytep dp = sp + (png_size_t)row_width * 4; 1.2876 + for (i = 0; i < row_width; i++) 1.2877 + { 1.2878 + *(dp--) = *sp; 1.2879 + *(dp--) = *(sp - 1); 1.2880 + *(dp--) = *sp; 1.2881 + *(dp--) = *(sp - 1); 1.2882 + *(dp--) = *(sp--); 1.2883 + *(dp--) = *(sp--); 1.2884 + } 1.2885 + } 1.2886 + } 1.2887 + 1.2888 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.2889 + { 1.2890 + if (row_info->bit_depth == 8) 1.2891 + { 1.2892 + /* This changes GA to RGBA */ 1.2893 + png_bytep sp = row + (png_size_t)row_width * 2 - 1; 1.2894 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2895 + for (i = 0; i < row_width; i++) 1.2896 + { 1.2897 + *(dp--) = *(sp--); 1.2898 + *(dp--) = *sp; 1.2899 + *(dp--) = *sp; 1.2900 + *(dp--) = *(sp--); 1.2901 + } 1.2902 + } 1.2903 + 1.2904 + else 1.2905 + { 1.2906 + /* This changes GGAA to RRGGBBAA */ 1.2907 + png_bytep sp = row + (png_size_t)row_width * 4 - 1; 1.2908 + png_bytep dp = sp + (png_size_t)row_width * 4; 1.2909 + for (i = 0; i < row_width; i++) 1.2910 + { 1.2911 + *(dp--) = *(sp--); 1.2912 + *(dp--) = *(sp--); 1.2913 + *(dp--) = *sp; 1.2914 + *(dp--) = *(sp - 1); 1.2915 + *(dp--) = *sp; 1.2916 + *(dp--) = *(sp - 1); 1.2917 + *(dp--) = *(sp--); 1.2918 + *(dp--) = *(sp--); 1.2919 + } 1.2920 + } 1.2921 + } 1.2922 + row_info->channels = (png_byte)(row_info->channels + 2); 1.2923 + row_info->color_type |= PNG_COLOR_MASK_COLOR; 1.2924 + row_info->pixel_depth = (png_byte)(row_info->channels * 1.2925 + row_info->bit_depth); 1.2926 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.2927 + } 1.2928 +} 1.2929 +#endif 1.2930 + 1.2931 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.2932 +/* Reduce RGB files to grayscale, with or without alpha 1.2933 + * using the equation given in Poynton's ColorFAQ of 1998-01-04 at 1.2934 + * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but 1.2935 + * versions dated 1998 through November 2002 have been archived at 1.2936 + * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ 1.2937 + * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) 1.2938 + * Charles Poynton poynton at poynton.com 1.2939 + * 1.2940 + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 1.2941 + * 1.2942 + * which can be expressed with integers as 1.2943 + * 1.2944 + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 1.2945 + * 1.2946 + * Poynton's current link (as of January 2003 through July 2011): 1.2947 + * <http://www.poynton.com/notes/colour_and_gamma/> 1.2948 + * has changed the numbers slightly: 1.2949 + * 1.2950 + * Y = 0.2126*R + 0.7152*G + 0.0722*B 1.2951 + * 1.2952 + * which can be expressed with integers as 1.2953 + * 1.2954 + * Y = (6966 * R + 23436 * G + 2366 * B)/32768 1.2955 + * 1.2956 + * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 1.2957 + * end point chromaticities and the D65 white point. Depending on the 1.2958 + * precision used for the D65 white point this produces a variety of different 1.2959 + * numbers, however if the four decimal place value used in ITU-R Rec 709 is 1.2960 + * used (0.3127,0.3290) the Y calculation would be: 1.2961 + * 1.2962 + * Y = (6968 * R + 23435 * G + 2366 * B)/32768 1.2963 + * 1.2964 + * While this is correct the rounding results in an overflow for white, because 1.2965 + * the sum of the rounded coefficients is 32769, not 32768. Consequently 1.2966 + * libpng uses, instead, the closest non-overflowing approximation: 1.2967 + * 1.2968 + * Y = (6968 * R + 23434 * G + 2366 * B)/32768 1.2969 + * 1.2970 + * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk 1.2971 + * (including an sRGB chunk) then the chromaticities are used to calculate the 1.2972 + * coefficients. See the chunk handling in pngrutil.c for more information. 1.2973 + * 1.2974 + * In all cases the calculation is to be done in a linear colorspace. If no 1.2975 + * gamma information is available to correct the encoding of the original RGB 1.2976 + * values this results in an implicit assumption that the original PNG RGB 1.2977 + * values were linear. 1.2978 + * 1.2979 + * Other integer coefficents can be used via png_set_rgb_to_gray(). Because 1.2980 + * the API takes just red and green coefficients the blue coefficient is 1.2981 + * calculated to make the sum 32768. This will result in different rounding 1.2982 + * to that used above. 1.2983 + */ 1.2984 +static int 1.2985 +png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) 1.2986 + 1.2987 +{ 1.2988 + int rgb_error = 0; 1.2989 + 1.2990 + png_debug(1, "in png_do_rgb_to_gray"); 1.2991 + 1.2992 + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && 1.2993 + (row_info->color_type & PNG_COLOR_MASK_COLOR)) 1.2994 + { 1.2995 + PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 1.2996 + PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 1.2997 + PNG_CONST png_uint_32 bc = 32768 - rc - gc; 1.2998 + PNG_CONST png_uint_32 row_width = row_info->width; 1.2999 + PNG_CONST int have_alpha = 1.3000 + (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; 1.3001 + 1.3002 + if (row_info->bit_depth == 8) 1.3003 + { 1.3004 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3005 + /* Notice that gamma to/from 1 are not necessarily inverses (if 1.3006 + * there is an overall gamma correction). Prior to 1.5.5 this code 1.3007 + * checked the linearized values for equality; this doesn't match 1.3008 + * the documentation, the original values must be checked. 1.3009 + */ 1.3010 + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 1.3011 + { 1.3012 + png_bytep sp = row; 1.3013 + png_bytep dp = row; 1.3014 + png_uint_32 i; 1.3015 + 1.3016 + for (i = 0; i < row_width; i++) 1.3017 + { 1.3018 + png_byte red = *(sp++); 1.3019 + png_byte green = *(sp++); 1.3020 + png_byte blue = *(sp++); 1.3021 + 1.3022 + if (red != green || red != blue) 1.3023 + { 1.3024 + red = png_ptr->gamma_to_1[red]; 1.3025 + green = png_ptr->gamma_to_1[green]; 1.3026 + blue = png_ptr->gamma_to_1[blue]; 1.3027 + 1.3028 + rgb_error |= 1; 1.3029 + *(dp++) = png_ptr->gamma_from_1[ 1.3030 + (rc*red + gc*green + bc*blue + 16384)>>15]; 1.3031 + } 1.3032 + 1.3033 + else 1.3034 + { 1.3035 + /* If there is no overall correction the table will not be 1.3036 + * set. 1.3037 + */ 1.3038 + if (png_ptr->gamma_table != NULL) 1.3039 + red = png_ptr->gamma_table[red]; 1.3040 + 1.3041 + *(dp++) = red; 1.3042 + } 1.3043 + 1.3044 + if (have_alpha) 1.3045 + *(dp++) = *(sp++); 1.3046 + } 1.3047 + } 1.3048 + else 1.3049 +#endif 1.3050 + { 1.3051 + png_bytep sp = row; 1.3052 + png_bytep dp = row; 1.3053 + png_uint_32 i; 1.3054 + 1.3055 + for (i = 0; i < row_width; i++) 1.3056 + { 1.3057 + png_byte red = *(sp++); 1.3058 + png_byte green = *(sp++); 1.3059 + png_byte blue = *(sp++); 1.3060 + 1.3061 + if (red != green || red != blue) 1.3062 + { 1.3063 + rgb_error |= 1; 1.3064 + /* NOTE: this is the historical approach which simply 1.3065 + * truncates the results. 1.3066 + */ 1.3067 + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 1.3068 + } 1.3069 + 1.3070 + else 1.3071 + *(dp++) = red; 1.3072 + 1.3073 + if (have_alpha) 1.3074 + *(dp++) = *(sp++); 1.3075 + } 1.3076 + } 1.3077 + } 1.3078 + 1.3079 + else /* RGB bit_depth == 16 */ 1.3080 + { 1.3081 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3082 + if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) 1.3083 + { 1.3084 + png_bytep sp = row; 1.3085 + png_bytep dp = row; 1.3086 + png_uint_32 i; 1.3087 + 1.3088 + for (i = 0; i < row_width; i++) 1.3089 + { 1.3090 + png_uint_16 red, green, blue, w; 1.3091 + 1.3092 + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3093 + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3094 + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3095 + 1.3096 + if (red == green && red == blue) 1.3097 + { 1.3098 + if (png_ptr->gamma_16_table != NULL) 1.3099 + w = png_ptr->gamma_16_table[(red&0xff) 1.3100 + >> png_ptr->gamma_shift][red>>8]; 1.3101 + 1.3102 + else 1.3103 + w = red; 1.3104 + } 1.3105 + 1.3106 + else 1.3107 + { 1.3108 + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) 1.3109 + >> png_ptr->gamma_shift][red>>8]; 1.3110 + png_uint_16 green_1 = 1.3111 + png_ptr->gamma_16_to_1[(green&0xff) >> 1.3112 + png_ptr->gamma_shift][green>>8]; 1.3113 + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) 1.3114 + >> png_ptr->gamma_shift][blue>>8]; 1.3115 + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 1.3116 + + bc*blue_1 + 16384)>>15); 1.3117 + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 1.3118 + png_ptr->gamma_shift][gray16 >> 8]; 1.3119 + rgb_error |= 1; 1.3120 + } 1.3121 + 1.3122 + *(dp++) = (png_byte)((w>>8) & 0xff); 1.3123 + *(dp++) = (png_byte)(w & 0xff); 1.3124 + 1.3125 + if (have_alpha) 1.3126 + { 1.3127 + *(dp++) = *(sp++); 1.3128 + *(dp++) = *(sp++); 1.3129 + } 1.3130 + } 1.3131 + } 1.3132 + else 1.3133 +#endif 1.3134 + { 1.3135 + png_bytep sp = row; 1.3136 + png_bytep dp = row; 1.3137 + png_uint_32 i; 1.3138 + 1.3139 + for (i = 0; i < row_width; i++) 1.3140 + { 1.3141 + png_uint_16 red, green, blue, gray16; 1.3142 + 1.3143 + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3144 + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3145 + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 1.3146 + 1.3147 + if (red != green || red != blue) 1.3148 + rgb_error |= 1; 1.3149 + 1.3150 + /* From 1.5.5 in the 16 bit case do the accurate conversion even 1.3151 + * in the 'fast' case - this is because this is where the code 1.3152 + * ends up when handling linear 16 bit data. 1.3153 + */ 1.3154 + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> 1.3155 + 15); 1.3156 + *(dp++) = (png_byte)((gray16>>8) & 0xff); 1.3157 + *(dp++) = (png_byte)(gray16 & 0xff); 1.3158 + 1.3159 + if (have_alpha) 1.3160 + { 1.3161 + *(dp++) = *(sp++); 1.3162 + *(dp++) = *(sp++); 1.3163 + } 1.3164 + } 1.3165 + } 1.3166 + } 1.3167 + 1.3168 + row_info->channels = (png_byte)(row_info->channels - 2); 1.3169 + row_info->color_type = (png_byte)(row_info->color_type & 1.3170 + ~PNG_COLOR_MASK_COLOR); 1.3171 + row_info->pixel_depth = (png_byte)(row_info->channels * 1.3172 + row_info->bit_depth); 1.3173 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.3174 + } 1.3175 + return rgb_error; 1.3176 +} 1.3177 +#endif 1.3178 + 1.3179 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 1.3180 + defined(PNG_READ_ALPHA_MODE_SUPPORTED) 1.3181 +/* Replace any alpha or transparency with the supplied background color. 1.3182 + * "background" is already in the screen gamma, while "background_1" is 1.3183 + * at a gamma of 1.0. Paletted files have already been taken care of. 1.3184 + */ 1.3185 +static void 1.3186 +png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 1.3187 +{ 1.3188 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3189 + png_const_bytep gamma_table = png_ptr->gamma_table; 1.3190 + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; 1.3191 + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; 1.3192 + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; 1.3193 + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; 1.3194 + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; 1.3195 + int gamma_shift = png_ptr->gamma_shift; 1.3196 + int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; 1.3197 +#endif 1.3198 + 1.3199 + png_bytep sp; 1.3200 + png_uint_32 i; 1.3201 + png_uint_32 row_width = row_info->width; 1.3202 + int shift; 1.3203 + 1.3204 + png_debug(1, "in png_do_compose"); 1.3205 + 1.3206 + { 1.3207 + switch (row_info->color_type) 1.3208 + { 1.3209 + case PNG_COLOR_TYPE_GRAY: 1.3210 + { 1.3211 + switch (row_info->bit_depth) 1.3212 + { 1.3213 + case 1: 1.3214 + { 1.3215 + sp = row; 1.3216 + shift = 7; 1.3217 + for (i = 0; i < row_width; i++) 1.3218 + { 1.3219 + if ((png_uint_16)((*sp >> shift) & 0x01) 1.3220 + == png_ptr->trans_color.gray) 1.3221 + { 1.3222 + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); 1.3223 + tmp |= png_ptr->background.gray << shift; 1.3224 + *sp = (png_byte)(tmp & 0xff); 1.3225 + } 1.3226 + 1.3227 + if (!shift) 1.3228 + { 1.3229 + shift = 7; 1.3230 + sp++; 1.3231 + } 1.3232 + 1.3233 + else 1.3234 + shift--; 1.3235 + } 1.3236 + break; 1.3237 + } 1.3238 + 1.3239 + case 2: 1.3240 + { 1.3241 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3242 + if (gamma_table != NULL) 1.3243 + { 1.3244 + sp = row; 1.3245 + shift = 6; 1.3246 + for (i = 0; i < row_width; i++) 1.3247 + { 1.3248 + if ((png_uint_16)((*sp >> shift) & 0x03) 1.3249 + == png_ptr->trans_color.gray) 1.3250 + { 1.3251 + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 1.3252 + tmp |= png_ptr->background.gray << shift; 1.3253 + *sp = (png_byte)(tmp & 0xff); 1.3254 + } 1.3255 + 1.3256 + else 1.3257 + { 1.3258 + unsigned int p = (*sp >> shift) & 0x03; 1.3259 + unsigned int g = (gamma_table [p | (p << 2) | 1.3260 + (p << 4) | (p << 6)] >> 6) & 0x03; 1.3261 + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 1.3262 + tmp |= g << shift; 1.3263 + *sp = (png_byte)(tmp & 0xff); 1.3264 + } 1.3265 + 1.3266 + if (!shift) 1.3267 + { 1.3268 + shift = 6; 1.3269 + sp++; 1.3270 + } 1.3271 + 1.3272 + else 1.3273 + shift -= 2; 1.3274 + } 1.3275 + } 1.3276 + 1.3277 + else 1.3278 +#endif 1.3279 + { 1.3280 + sp = row; 1.3281 + shift = 6; 1.3282 + for (i = 0; i < row_width; i++) 1.3283 + { 1.3284 + if ((png_uint_16)((*sp >> shift) & 0x03) 1.3285 + == png_ptr->trans_color.gray) 1.3286 + { 1.3287 + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 1.3288 + tmp |= png_ptr->background.gray << shift; 1.3289 + *sp = (png_byte)(tmp & 0xff); 1.3290 + } 1.3291 + 1.3292 + if (!shift) 1.3293 + { 1.3294 + shift = 6; 1.3295 + sp++; 1.3296 + } 1.3297 + 1.3298 + else 1.3299 + shift -= 2; 1.3300 + } 1.3301 + } 1.3302 + break; 1.3303 + } 1.3304 + 1.3305 + case 4: 1.3306 + { 1.3307 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3308 + if (gamma_table != NULL) 1.3309 + { 1.3310 + sp = row; 1.3311 + shift = 4; 1.3312 + for (i = 0; i < row_width; i++) 1.3313 + { 1.3314 + if ((png_uint_16)((*sp >> shift) & 0x0f) 1.3315 + == png_ptr->trans_color.gray) 1.3316 + { 1.3317 + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); 1.3318 + tmp |= png_ptr->background.gray << shift; 1.3319 + *sp = (png_byte)(tmp & 0xff); 1.3320 + } 1.3321 + 1.3322 + else 1.3323 + { 1.3324 + unsigned int p = (*sp >> shift) & 0x0f; 1.3325 + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & 1.3326 + 0x0f; 1.3327 + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); 1.3328 + tmp |= g << shift; 1.3329 + *sp = (png_byte)(tmp & 0xff); 1.3330 + } 1.3331 + 1.3332 + if (!shift) 1.3333 + { 1.3334 + shift = 4; 1.3335 + sp++; 1.3336 + } 1.3337 + 1.3338 + else 1.3339 + shift -= 4; 1.3340 + } 1.3341 + } 1.3342 + 1.3343 + else 1.3344 +#endif 1.3345 + { 1.3346 + sp = row; 1.3347 + shift = 4; 1.3348 + for (i = 0; i < row_width; i++) 1.3349 + { 1.3350 + if ((png_uint_16)((*sp >> shift) & 0x0f) 1.3351 + == png_ptr->trans_color.gray) 1.3352 + { 1.3353 + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); 1.3354 + tmp |= png_ptr->background.gray << shift; 1.3355 + *sp = (png_byte)(tmp & 0xff); 1.3356 + } 1.3357 + 1.3358 + if (!shift) 1.3359 + { 1.3360 + shift = 4; 1.3361 + sp++; 1.3362 + } 1.3363 + 1.3364 + else 1.3365 + shift -= 4; 1.3366 + } 1.3367 + } 1.3368 + break; 1.3369 + } 1.3370 + 1.3371 + case 8: 1.3372 + { 1.3373 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3374 + if (gamma_table != NULL) 1.3375 + { 1.3376 + sp = row; 1.3377 + for (i = 0; i < row_width; i++, sp++) 1.3378 + { 1.3379 + if (*sp == png_ptr->trans_color.gray) 1.3380 + *sp = (png_byte)png_ptr->background.gray; 1.3381 + 1.3382 + else 1.3383 + *sp = gamma_table[*sp]; 1.3384 + } 1.3385 + } 1.3386 + else 1.3387 +#endif 1.3388 + { 1.3389 + sp = row; 1.3390 + for (i = 0; i < row_width; i++, sp++) 1.3391 + { 1.3392 + if (*sp == png_ptr->trans_color.gray) 1.3393 + *sp = (png_byte)png_ptr->background.gray; 1.3394 + } 1.3395 + } 1.3396 + break; 1.3397 + } 1.3398 + 1.3399 + case 16: 1.3400 + { 1.3401 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3402 + if (gamma_16 != NULL) 1.3403 + { 1.3404 + sp = row; 1.3405 + for (i = 0; i < row_width; i++, sp += 2) 1.3406 + { 1.3407 + png_uint_16 v; 1.3408 + 1.3409 + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3410 + 1.3411 + if (v == png_ptr->trans_color.gray) 1.3412 + { 1.3413 + /* Background is already in screen gamma */ 1.3414 + *sp = (png_byte)((png_ptr->background.gray >> 8) 1.3415 + & 0xff); 1.3416 + *(sp + 1) = (png_byte)(png_ptr->background.gray 1.3417 + & 0xff); 1.3418 + } 1.3419 + 1.3420 + else 1.3421 + { 1.3422 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3423 + *sp = (png_byte)((v >> 8) & 0xff); 1.3424 + *(sp + 1) = (png_byte)(v & 0xff); 1.3425 + } 1.3426 + } 1.3427 + } 1.3428 + else 1.3429 +#endif 1.3430 + { 1.3431 + sp = row; 1.3432 + for (i = 0; i < row_width; i++, sp += 2) 1.3433 + { 1.3434 + png_uint_16 v; 1.3435 + 1.3436 + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3437 + 1.3438 + if (v == png_ptr->trans_color.gray) 1.3439 + { 1.3440 + *sp = (png_byte)((png_ptr->background.gray >> 8) 1.3441 + & 0xff); 1.3442 + *(sp + 1) = (png_byte)(png_ptr->background.gray 1.3443 + & 0xff); 1.3444 + } 1.3445 + } 1.3446 + } 1.3447 + break; 1.3448 + } 1.3449 + 1.3450 + default: 1.3451 + break; 1.3452 + } 1.3453 + break; 1.3454 + } 1.3455 + 1.3456 + case PNG_COLOR_TYPE_RGB: 1.3457 + { 1.3458 + if (row_info->bit_depth == 8) 1.3459 + { 1.3460 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3461 + if (gamma_table != NULL) 1.3462 + { 1.3463 + sp = row; 1.3464 + for (i = 0; i < row_width; i++, sp += 3) 1.3465 + { 1.3466 + if (*sp == png_ptr->trans_color.red && 1.3467 + *(sp + 1) == png_ptr->trans_color.green && 1.3468 + *(sp + 2) == png_ptr->trans_color.blue) 1.3469 + { 1.3470 + *sp = (png_byte)png_ptr->background.red; 1.3471 + *(sp + 1) = (png_byte)png_ptr->background.green; 1.3472 + *(sp + 2) = (png_byte)png_ptr->background.blue; 1.3473 + } 1.3474 + 1.3475 + else 1.3476 + { 1.3477 + *sp = gamma_table[*sp]; 1.3478 + *(sp + 1) = gamma_table[*(sp + 1)]; 1.3479 + *(sp + 2) = gamma_table[*(sp + 2)]; 1.3480 + } 1.3481 + } 1.3482 + } 1.3483 + else 1.3484 +#endif 1.3485 + { 1.3486 + sp = row; 1.3487 + for (i = 0; i < row_width; i++, sp += 3) 1.3488 + { 1.3489 + if (*sp == png_ptr->trans_color.red && 1.3490 + *(sp + 1) == png_ptr->trans_color.green && 1.3491 + *(sp + 2) == png_ptr->trans_color.blue) 1.3492 + { 1.3493 + *sp = (png_byte)png_ptr->background.red; 1.3494 + *(sp + 1) = (png_byte)png_ptr->background.green; 1.3495 + *(sp + 2) = (png_byte)png_ptr->background.blue; 1.3496 + } 1.3497 + } 1.3498 + } 1.3499 + } 1.3500 + else /* if (row_info->bit_depth == 16) */ 1.3501 + { 1.3502 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3503 + if (gamma_16 != NULL) 1.3504 + { 1.3505 + sp = row; 1.3506 + for (i = 0; i < row_width; i++, sp += 6) 1.3507 + { 1.3508 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3509 + 1.3510 + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 1.3511 + + *(sp + 3)); 1.3512 + 1.3513 + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 1.3514 + + *(sp + 5)); 1.3515 + 1.3516 + if (r == png_ptr->trans_color.red && 1.3517 + g == png_ptr->trans_color.green && 1.3518 + b == png_ptr->trans_color.blue) 1.3519 + { 1.3520 + /* Background is already in screen gamma */ 1.3521 + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 1.3522 + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 1.3523 + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 1.3524 + & 0xff); 1.3525 + *(sp + 3) = (png_byte)(png_ptr->background.green 1.3526 + & 0xff); 1.3527 + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 1.3528 + & 0xff); 1.3529 + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 1.3530 + } 1.3531 + 1.3532 + else 1.3533 + { 1.3534 + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3535 + *sp = (png_byte)((v >> 8) & 0xff); 1.3536 + *(sp + 1) = (png_byte)(v & 0xff); 1.3537 + 1.3538 + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3539 + *(sp + 2) = (png_byte)((v >> 8) & 0xff); 1.3540 + *(sp + 3) = (png_byte)(v & 0xff); 1.3541 + 1.3542 + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3543 + *(sp + 4) = (png_byte)((v >> 8) & 0xff); 1.3544 + *(sp + 5) = (png_byte)(v & 0xff); 1.3545 + } 1.3546 + } 1.3547 + } 1.3548 + 1.3549 + else 1.3550 +#endif 1.3551 + { 1.3552 + sp = row; 1.3553 + for (i = 0; i < row_width; i++, sp += 6) 1.3554 + { 1.3555 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3556 + 1.3557 + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 1.3558 + + *(sp + 3)); 1.3559 + 1.3560 + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 1.3561 + + *(sp + 5)); 1.3562 + 1.3563 + if (r == png_ptr->trans_color.red && 1.3564 + g == png_ptr->trans_color.green && 1.3565 + b == png_ptr->trans_color.blue) 1.3566 + { 1.3567 + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 1.3568 + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 1.3569 + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 1.3570 + & 0xff); 1.3571 + *(sp + 3) = (png_byte)(png_ptr->background.green 1.3572 + & 0xff); 1.3573 + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 1.3574 + & 0xff); 1.3575 + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 1.3576 + } 1.3577 + } 1.3578 + } 1.3579 + } 1.3580 + break; 1.3581 + } 1.3582 + 1.3583 + case PNG_COLOR_TYPE_GRAY_ALPHA: 1.3584 + { 1.3585 + if (row_info->bit_depth == 8) 1.3586 + { 1.3587 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3588 + if (gamma_to_1 != NULL && gamma_from_1 != NULL && 1.3589 + gamma_table != NULL) 1.3590 + { 1.3591 + sp = row; 1.3592 + for (i = 0; i < row_width; i++, sp += 2) 1.3593 + { 1.3594 + png_uint_16 a = *(sp + 1); 1.3595 + 1.3596 + if (a == 0xff) 1.3597 + *sp = gamma_table[*sp]; 1.3598 + 1.3599 + else if (a == 0) 1.3600 + { 1.3601 + /* Background is already in screen gamma */ 1.3602 + *sp = (png_byte)png_ptr->background.gray; 1.3603 + } 1.3604 + 1.3605 + else 1.3606 + { 1.3607 + png_byte v, w; 1.3608 + 1.3609 + v = gamma_to_1[*sp]; 1.3610 + png_composite(w, v, a, png_ptr->background_1.gray); 1.3611 + if (!optimize) 1.3612 + w = gamma_from_1[w]; 1.3613 + *sp = w; 1.3614 + } 1.3615 + } 1.3616 + } 1.3617 + else 1.3618 +#endif 1.3619 + { 1.3620 + sp = row; 1.3621 + for (i = 0; i < row_width; i++, sp += 2) 1.3622 + { 1.3623 + png_byte a = *(sp + 1); 1.3624 + 1.3625 + if (a == 0) 1.3626 + *sp = (png_byte)png_ptr->background.gray; 1.3627 + 1.3628 + else if (a < 0xff) 1.3629 + png_composite(*sp, *sp, a, png_ptr->background.gray); 1.3630 + } 1.3631 + } 1.3632 + } 1.3633 + else /* if (png_ptr->bit_depth == 16) */ 1.3634 + { 1.3635 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3636 + if (gamma_16 != NULL && gamma_16_from_1 != NULL && 1.3637 + gamma_16_to_1 != NULL) 1.3638 + { 1.3639 + sp = row; 1.3640 + for (i = 0; i < row_width; i++, sp += 4) 1.3641 + { 1.3642 + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 1.3643 + + *(sp + 3)); 1.3644 + 1.3645 + if (a == (png_uint_16)0xffff) 1.3646 + { 1.3647 + png_uint_16 v; 1.3648 + 1.3649 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3650 + *sp = (png_byte)((v >> 8) & 0xff); 1.3651 + *(sp + 1) = (png_byte)(v & 0xff); 1.3652 + } 1.3653 + 1.3654 + else if (a == 0) 1.3655 + { 1.3656 + /* Background is already in screen gamma */ 1.3657 + *sp = (png_byte)((png_ptr->background.gray >> 8) 1.3658 + & 0xff); 1.3659 + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 1.3660 + } 1.3661 + 1.3662 + else 1.3663 + { 1.3664 + png_uint_16 g, v, w; 1.3665 + 1.3666 + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 1.3667 + png_composite_16(v, g, a, png_ptr->background_1.gray); 1.3668 + if (optimize) 1.3669 + w = v; 1.3670 + else 1.3671 + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; 1.3672 + *sp = (png_byte)((w >> 8) & 0xff); 1.3673 + *(sp + 1) = (png_byte)(w & 0xff); 1.3674 + } 1.3675 + } 1.3676 + } 1.3677 + else 1.3678 +#endif 1.3679 + { 1.3680 + sp = row; 1.3681 + for (i = 0; i < row_width; i++, sp += 4) 1.3682 + { 1.3683 + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 1.3684 + + *(sp + 3)); 1.3685 + 1.3686 + if (a == 0) 1.3687 + { 1.3688 + *sp = (png_byte)((png_ptr->background.gray >> 8) 1.3689 + & 0xff); 1.3690 + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 1.3691 + } 1.3692 + 1.3693 + else if (a < 0xffff) 1.3694 + { 1.3695 + png_uint_16 g, v; 1.3696 + 1.3697 + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3698 + png_composite_16(v, g, a, png_ptr->background.gray); 1.3699 + *sp = (png_byte)((v >> 8) & 0xff); 1.3700 + *(sp + 1) = (png_byte)(v & 0xff); 1.3701 + } 1.3702 + } 1.3703 + } 1.3704 + } 1.3705 + break; 1.3706 + } 1.3707 + 1.3708 + case PNG_COLOR_TYPE_RGB_ALPHA: 1.3709 + { 1.3710 + if (row_info->bit_depth == 8) 1.3711 + { 1.3712 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3713 + if (gamma_to_1 != NULL && gamma_from_1 != NULL && 1.3714 + gamma_table != NULL) 1.3715 + { 1.3716 + sp = row; 1.3717 + for (i = 0; i < row_width; i++, sp += 4) 1.3718 + { 1.3719 + png_byte a = *(sp + 3); 1.3720 + 1.3721 + if (a == 0xff) 1.3722 + { 1.3723 + *sp = gamma_table[*sp]; 1.3724 + *(sp + 1) = gamma_table[*(sp + 1)]; 1.3725 + *(sp + 2) = gamma_table[*(sp + 2)]; 1.3726 + } 1.3727 + 1.3728 + else if (a == 0) 1.3729 + { 1.3730 + /* Background is already in screen gamma */ 1.3731 + *sp = (png_byte)png_ptr->background.red; 1.3732 + *(sp + 1) = (png_byte)png_ptr->background.green; 1.3733 + *(sp + 2) = (png_byte)png_ptr->background.blue; 1.3734 + } 1.3735 + 1.3736 + else 1.3737 + { 1.3738 + png_byte v, w; 1.3739 + 1.3740 + v = gamma_to_1[*sp]; 1.3741 + png_composite(w, v, a, png_ptr->background_1.red); 1.3742 + if (!optimize) w = gamma_from_1[w]; 1.3743 + *sp = w; 1.3744 + 1.3745 + v = gamma_to_1[*(sp + 1)]; 1.3746 + png_composite(w, v, a, png_ptr->background_1.green); 1.3747 + if (!optimize) w = gamma_from_1[w]; 1.3748 + *(sp + 1) = w; 1.3749 + 1.3750 + v = gamma_to_1[*(sp + 2)]; 1.3751 + png_composite(w, v, a, png_ptr->background_1.blue); 1.3752 + if (!optimize) w = gamma_from_1[w]; 1.3753 + *(sp + 2) = w; 1.3754 + } 1.3755 + } 1.3756 + } 1.3757 + else 1.3758 +#endif 1.3759 + { 1.3760 + sp = row; 1.3761 + for (i = 0; i < row_width; i++, sp += 4) 1.3762 + { 1.3763 + png_byte a = *(sp + 3); 1.3764 + 1.3765 + if (a == 0) 1.3766 + { 1.3767 + *sp = (png_byte)png_ptr->background.red; 1.3768 + *(sp + 1) = (png_byte)png_ptr->background.green; 1.3769 + *(sp + 2) = (png_byte)png_ptr->background.blue; 1.3770 + } 1.3771 + 1.3772 + else if (a < 0xff) 1.3773 + { 1.3774 + png_composite(*sp, *sp, a, png_ptr->background.red); 1.3775 + 1.3776 + png_composite(*(sp + 1), *(sp + 1), a, 1.3777 + png_ptr->background.green); 1.3778 + 1.3779 + png_composite(*(sp + 2), *(sp + 2), a, 1.3780 + png_ptr->background.blue); 1.3781 + } 1.3782 + } 1.3783 + } 1.3784 + } 1.3785 + else /* if (row_info->bit_depth == 16) */ 1.3786 + { 1.3787 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3788 + if (gamma_16 != NULL && gamma_16_from_1 != NULL && 1.3789 + gamma_16_to_1 != NULL) 1.3790 + { 1.3791 + sp = row; 1.3792 + for (i = 0; i < row_width; i++, sp += 8) 1.3793 + { 1.3794 + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 1.3795 + << 8) + (png_uint_16)(*(sp + 7))); 1.3796 + 1.3797 + if (a == (png_uint_16)0xffff) 1.3798 + { 1.3799 + png_uint_16 v; 1.3800 + 1.3801 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3802 + *sp = (png_byte)((v >> 8) & 0xff); 1.3803 + *(sp + 1) = (png_byte)(v & 0xff); 1.3804 + 1.3805 + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3806 + *(sp + 2) = (png_byte)((v >> 8) & 0xff); 1.3807 + *(sp + 3) = (png_byte)(v & 0xff); 1.3808 + 1.3809 + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3810 + *(sp + 4) = (png_byte)((v >> 8) & 0xff); 1.3811 + *(sp + 5) = (png_byte)(v & 0xff); 1.3812 + } 1.3813 + 1.3814 + else if (a == 0) 1.3815 + { 1.3816 + /* Background is already in screen gamma */ 1.3817 + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 1.3818 + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 1.3819 + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 1.3820 + & 0xff); 1.3821 + *(sp + 3) = (png_byte)(png_ptr->background.green 1.3822 + & 0xff); 1.3823 + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 1.3824 + & 0xff); 1.3825 + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 1.3826 + } 1.3827 + 1.3828 + else 1.3829 + { 1.3830 + png_uint_16 v, w; 1.3831 + 1.3832 + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 1.3833 + png_composite_16(w, v, a, png_ptr->background_1.red); 1.3834 + if (!optimize) 1.3835 + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 1.3836 + 8]; 1.3837 + *sp = (png_byte)((w >> 8) & 0xff); 1.3838 + *(sp + 1) = (png_byte)(w & 0xff); 1.3839 + 1.3840 + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3841 + png_composite_16(w, v, a, png_ptr->background_1.green); 1.3842 + if (!optimize) 1.3843 + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 1.3844 + 8]; 1.3845 + 1.3846 + *(sp + 2) = (png_byte)((w >> 8) & 0xff); 1.3847 + *(sp + 3) = (png_byte)(w & 0xff); 1.3848 + 1.3849 + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3850 + png_composite_16(w, v, a, png_ptr->background_1.blue); 1.3851 + if (!optimize) 1.3852 + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 1.3853 + 8]; 1.3854 + 1.3855 + *(sp + 4) = (png_byte)((w >> 8) & 0xff); 1.3856 + *(sp + 5) = (png_byte)(w & 0xff); 1.3857 + } 1.3858 + } 1.3859 + } 1.3860 + 1.3861 + else 1.3862 +#endif 1.3863 + { 1.3864 + sp = row; 1.3865 + for (i = 0; i < row_width; i++, sp += 8) 1.3866 + { 1.3867 + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 1.3868 + << 8) + (png_uint_16)(*(sp + 7))); 1.3869 + 1.3870 + if (a == 0) 1.3871 + { 1.3872 + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 1.3873 + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 1.3874 + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 1.3875 + & 0xff); 1.3876 + *(sp + 3) = (png_byte)(png_ptr->background.green 1.3877 + & 0xff); 1.3878 + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 1.3879 + & 0xff); 1.3880 + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 1.3881 + } 1.3882 + 1.3883 + else if (a < 0xffff) 1.3884 + { 1.3885 + png_uint_16 v; 1.3886 + 1.3887 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3888 + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 1.3889 + + *(sp + 3)); 1.3890 + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 1.3891 + + *(sp + 5)); 1.3892 + 1.3893 + png_composite_16(v, r, a, png_ptr->background.red); 1.3894 + *sp = (png_byte)((v >> 8) & 0xff); 1.3895 + *(sp + 1) = (png_byte)(v & 0xff); 1.3896 + 1.3897 + png_composite_16(v, g, a, png_ptr->background.green); 1.3898 + *(sp + 2) = (png_byte)((v >> 8) & 0xff); 1.3899 + *(sp + 3) = (png_byte)(v & 0xff); 1.3900 + 1.3901 + png_composite_16(v, b, a, png_ptr->background.blue); 1.3902 + *(sp + 4) = (png_byte)((v >> 8) & 0xff); 1.3903 + *(sp + 5) = (png_byte)(v & 0xff); 1.3904 + } 1.3905 + } 1.3906 + } 1.3907 + } 1.3908 + break; 1.3909 + } 1.3910 + 1.3911 + default: 1.3912 + break; 1.3913 + } 1.3914 + } 1.3915 +} 1.3916 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ 1.3917 + 1.3918 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.3919 +/* Gamma correct the image, avoiding the alpha channel. Make sure 1.3920 + * you do this after you deal with the transparency issue on grayscale 1.3921 + * or RGB images. If your bit depth is 8, use gamma_table, if it 1.3922 + * is 16, use gamma_16_table and gamma_shift. Build these with 1.3923 + * build_gamma_table(). 1.3924 + */ 1.3925 +static void 1.3926 +png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 1.3927 +{ 1.3928 + png_const_bytep gamma_table = png_ptr->gamma_table; 1.3929 + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; 1.3930 + int gamma_shift = png_ptr->gamma_shift; 1.3931 + 1.3932 + png_bytep sp; 1.3933 + png_uint_32 i; 1.3934 + png_uint_32 row_width=row_info->width; 1.3935 + 1.3936 + png_debug(1, "in png_do_gamma"); 1.3937 + 1.3938 + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || 1.3939 + (row_info->bit_depth == 16 && gamma_16_table != NULL))) 1.3940 + { 1.3941 + switch (row_info->color_type) 1.3942 + { 1.3943 + case PNG_COLOR_TYPE_RGB: 1.3944 + { 1.3945 + if (row_info->bit_depth == 8) 1.3946 + { 1.3947 + sp = row; 1.3948 + for (i = 0; i < row_width; i++) 1.3949 + { 1.3950 + *sp = gamma_table[*sp]; 1.3951 + sp++; 1.3952 + *sp = gamma_table[*sp]; 1.3953 + sp++; 1.3954 + *sp = gamma_table[*sp]; 1.3955 + sp++; 1.3956 + } 1.3957 + } 1.3958 + 1.3959 + else /* if (row_info->bit_depth == 16) */ 1.3960 + { 1.3961 + sp = row; 1.3962 + for (i = 0; i < row_width; i++) 1.3963 + { 1.3964 + png_uint_16 v; 1.3965 + 1.3966 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3967 + *sp = (png_byte)((v >> 8) & 0xff); 1.3968 + *(sp + 1) = (png_byte)(v & 0xff); 1.3969 + sp += 2; 1.3970 + 1.3971 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3972 + *sp = (png_byte)((v >> 8) & 0xff); 1.3973 + *(sp + 1) = (png_byte)(v & 0xff); 1.3974 + sp += 2; 1.3975 + 1.3976 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3977 + *sp = (png_byte)((v >> 8) & 0xff); 1.3978 + *(sp + 1) = (png_byte)(v & 0xff); 1.3979 + sp += 2; 1.3980 + } 1.3981 + } 1.3982 + break; 1.3983 + } 1.3984 + 1.3985 + case PNG_COLOR_TYPE_RGB_ALPHA: 1.3986 + { 1.3987 + if (row_info->bit_depth == 8) 1.3988 + { 1.3989 + sp = row; 1.3990 + for (i = 0; i < row_width; i++) 1.3991 + { 1.3992 + *sp = gamma_table[*sp]; 1.3993 + sp++; 1.3994 + 1.3995 + *sp = gamma_table[*sp]; 1.3996 + sp++; 1.3997 + 1.3998 + *sp = gamma_table[*sp]; 1.3999 + sp++; 1.4000 + 1.4001 + sp++; 1.4002 + } 1.4003 + } 1.4004 + 1.4005 + else /* if (row_info->bit_depth == 16) */ 1.4006 + { 1.4007 + sp = row; 1.4008 + for (i = 0; i < row_width; i++) 1.4009 + { 1.4010 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.4011 + *sp = (png_byte)((v >> 8) & 0xff); 1.4012 + *(sp + 1) = (png_byte)(v & 0xff); 1.4013 + sp += 2; 1.4014 + 1.4015 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.4016 + *sp = (png_byte)((v >> 8) & 0xff); 1.4017 + *(sp + 1) = (png_byte)(v & 0xff); 1.4018 + sp += 2; 1.4019 + 1.4020 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.4021 + *sp = (png_byte)((v >> 8) & 0xff); 1.4022 + *(sp + 1) = (png_byte)(v & 0xff); 1.4023 + sp += 4; 1.4024 + } 1.4025 + } 1.4026 + break; 1.4027 + } 1.4028 + 1.4029 + case PNG_COLOR_TYPE_GRAY_ALPHA: 1.4030 + { 1.4031 + if (row_info->bit_depth == 8) 1.4032 + { 1.4033 + sp = row; 1.4034 + for (i = 0; i < row_width; i++) 1.4035 + { 1.4036 + *sp = gamma_table[*sp]; 1.4037 + sp += 2; 1.4038 + } 1.4039 + } 1.4040 + 1.4041 + else /* if (row_info->bit_depth == 16) */ 1.4042 + { 1.4043 + sp = row; 1.4044 + for (i = 0; i < row_width; i++) 1.4045 + { 1.4046 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.4047 + *sp = (png_byte)((v >> 8) & 0xff); 1.4048 + *(sp + 1) = (png_byte)(v & 0xff); 1.4049 + sp += 4; 1.4050 + } 1.4051 + } 1.4052 + break; 1.4053 + } 1.4054 + 1.4055 + case PNG_COLOR_TYPE_GRAY: 1.4056 + { 1.4057 + if (row_info->bit_depth == 2) 1.4058 + { 1.4059 + sp = row; 1.4060 + for (i = 0; i < row_width; i += 4) 1.4061 + { 1.4062 + int a = *sp & 0xc0; 1.4063 + int b = *sp & 0x30; 1.4064 + int c = *sp & 0x0c; 1.4065 + int d = *sp & 0x03; 1.4066 + 1.4067 + *sp = (png_byte)( 1.4068 + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 1.4069 + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 1.4070 + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 1.4071 + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 1.4072 + sp++; 1.4073 + } 1.4074 + } 1.4075 + 1.4076 + if (row_info->bit_depth == 4) 1.4077 + { 1.4078 + sp = row; 1.4079 + for (i = 0; i < row_width; i += 2) 1.4080 + { 1.4081 + int msb = *sp & 0xf0; 1.4082 + int lsb = *sp & 0x0f; 1.4083 + 1.4084 + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 1.4085 + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 1.4086 + sp++; 1.4087 + } 1.4088 + } 1.4089 + 1.4090 + else if (row_info->bit_depth == 8) 1.4091 + { 1.4092 + sp = row; 1.4093 + for (i = 0; i < row_width; i++) 1.4094 + { 1.4095 + *sp = gamma_table[*sp]; 1.4096 + sp++; 1.4097 + } 1.4098 + } 1.4099 + 1.4100 + else if (row_info->bit_depth == 16) 1.4101 + { 1.4102 + sp = row; 1.4103 + for (i = 0; i < row_width; i++) 1.4104 + { 1.4105 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.4106 + *sp = (png_byte)((v >> 8) & 0xff); 1.4107 + *(sp + 1) = (png_byte)(v & 0xff); 1.4108 + sp += 2; 1.4109 + } 1.4110 + } 1.4111 + break; 1.4112 + } 1.4113 + 1.4114 + default: 1.4115 + break; 1.4116 + } 1.4117 + } 1.4118 +} 1.4119 +#endif 1.4120 + 1.4121 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1.4122 +/* Encode the alpha channel to the output gamma (the input channel is always 1.4123 + * linear.) Called only with color types that have an alpha channel. Needs the 1.4124 + * from_1 tables. 1.4125 + */ 1.4126 +static void 1.4127 +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 1.4128 +{ 1.4129 + png_uint_32 row_width = row_info->width; 1.4130 + 1.4131 + png_debug(1, "in png_do_encode_alpha"); 1.4132 + 1.4133 + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 1.4134 + { 1.4135 + if (row_info->bit_depth == 8) 1.4136 + { 1.4137 + PNG_CONST png_bytep table = png_ptr->gamma_from_1; 1.4138 + 1.4139 + if (table != NULL) 1.4140 + { 1.4141 + PNG_CONST int step = 1.4142 + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; 1.4143 + 1.4144 + /* The alpha channel is the last component: */ 1.4145 + row += step - 1; 1.4146 + 1.4147 + for (; row_width > 0; --row_width, row += step) 1.4148 + *row = table[*row]; 1.4149 + 1.4150 + return; 1.4151 + } 1.4152 + } 1.4153 + 1.4154 + else if (row_info->bit_depth == 16) 1.4155 + { 1.4156 + PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; 1.4157 + PNG_CONST int gamma_shift = png_ptr->gamma_shift; 1.4158 + 1.4159 + if (table != NULL) 1.4160 + { 1.4161 + PNG_CONST int step = 1.4162 + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; 1.4163 + 1.4164 + /* The alpha channel is the last component: */ 1.4165 + row += step - 2; 1.4166 + 1.4167 + for (; row_width > 0; --row_width, row += step) 1.4168 + { 1.4169 + png_uint_16 v; 1.4170 + 1.4171 + v = table[*(row + 1) >> gamma_shift][*row]; 1.4172 + *row = (png_byte)((v >> 8) & 0xff); 1.4173 + *(row + 1) = (png_byte)(v & 0xff); 1.4174 + } 1.4175 + 1.4176 + return; 1.4177 + } 1.4178 + } 1.4179 + } 1.4180 + 1.4181 + /* Only get to here if called with a weird row_info; no harm has been done, 1.4182 + * so just issue a warning. 1.4183 + */ 1.4184 + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); 1.4185 +} 1.4186 +#endif 1.4187 + 1.4188 +#ifdef PNG_READ_EXPAND_SUPPORTED 1.4189 +/* Expands a palette row to an RGB or RGBA row depending 1.4190 + * upon whether you supply trans and num_trans. 1.4191 + */ 1.4192 +static void 1.4193 +png_do_expand_palette(png_row_infop row_info, png_bytep row, 1.4194 + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) 1.4195 +{ 1.4196 + int shift, value; 1.4197 + png_bytep sp, dp; 1.4198 + png_uint_32 i; 1.4199 + png_uint_32 row_width=row_info->width; 1.4200 + 1.4201 + png_debug(1, "in png_do_expand_palette"); 1.4202 + 1.4203 + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 1.4204 + { 1.4205 + if (row_info->bit_depth < 8) 1.4206 + { 1.4207 + switch (row_info->bit_depth) 1.4208 + { 1.4209 + case 1: 1.4210 + { 1.4211 + sp = row + (png_size_t)((row_width - 1) >> 3); 1.4212 + dp = row + (png_size_t)row_width - 1; 1.4213 + shift = 7 - (int)((row_width + 7) & 0x07); 1.4214 + for (i = 0; i < row_width; i++) 1.4215 + { 1.4216 + if ((*sp >> shift) & 0x01) 1.4217 + *dp = 1; 1.4218 + 1.4219 + else 1.4220 + *dp = 0; 1.4221 + 1.4222 + if (shift == 7) 1.4223 + { 1.4224 + shift = 0; 1.4225 + sp--; 1.4226 + } 1.4227 + 1.4228 + else 1.4229 + shift++; 1.4230 + 1.4231 + dp--; 1.4232 + } 1.4233 + break; 1.4234 + } 1.4235 + 1.4236 + case 2: 1.4237 + { 1.4238 + sp = row + (png_size_t)((row_width - 1) >> 2); 1.4239 + dp = row + (png_size_t)row_width - 1; 1.4240 + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.4241 + for (i = 0; i < row_width; i++) 1.4242 + { 1.4243 + value = (*sp >> shift) & 0x03; 1.4244 + *dp = (png_byte)value; 1.4245 + if (shift == 6) 1.4246 + { 1.4247 + shift = 0; 1.4248 + sp--; 1.4249 + } 1.4250 + 1.4251 + else 1.4252 + shift += 2; 1.4253 + 1.4254 + dp--; 1.4255 + } 1.4256 + break; 1.4257 + } 1.4258 + 1.4259 + case 4: 1.4260 + { 1.4261 + sp = row + (png_size_t)((row_width - 1) >> 1); 1.4262 + dp = row + (png_size_t)row_width - 1; 1.4263 + shift = (int)((row_width & 0x01) << 2); 1.4264 + for (i = 0; i < row_width; i++) 1.4265 + { 1.4266 + value = (*sp >> shift) & 0x0f; 1.4267 + *dp = (png_byte)value; 1.4268 + if (shift == 4) 1.4269 + { 1.4270 + shift = 0; 1.4271 + sp--; 1.4272 + } 1.4273 + 1.4274 + else 1.4275 + shift += 4; 1.4276 + 1.4277 + dp--; 1.4278 + } 1.4279 + break; 1.4280 + } 1.4281 + 1.4282 + default: 1.4283 + break; 1.4284 + } 1.4285 + row_info->bit_depth = 8; 1.4286 + row_info->pixel_depth = 8; 1.4287 + row_info->rowbytes = row_width; 1.4288 + } 1.4289 + 1.4290 + if (row_info->bit_depth == 8) 1.4291 + { 1.4292 + { 1.4293 + if (num_trans > 0) 1.4294 + { 1.4295 + sp = row + (png_size_t)row_width - 1; 1.4296 + dp = row + (png_size_t)(row_width << 2) - 1; 1.4297 + 1.4298 + for (i = 0; i < row_width; i++) 1.4299 + { 1.4300 + if ((int)(*sp) >= num_trans) 1.4301 + *dp-- = 0xff; 1.4302 + 1.4303 + else 1.4304 + *dp-- = trans_alpha[*sp]; 1.4305 + 1.4306 + *dp-- = palette[*sp].blue; 1.4307 + *dp-- = palette[*sp].green; 1.4308 + *dp-- = palette[*sp].red; 1.4309 + sp--; 1.4310 + } 1.4311 + row_info->bit_depth = 8; 1.4312 + row_info->pixel_depth = 32; 1.4313 + row_info->rowbytes = row_width * 4; 1.4314 + row_info->color_type = 6; 1.4315 + row_info->channels = 4; 1.4316 + } 1.4317 + 1.4318 + else 1.4319 + { 1.4320 + sp = row + (png_size_t)row_width - 1; 1.4321 + dp = row + (png_size_t)(row_width * 3) - 1; 1.4322 + 1.4323 + for (i = 0; i < row_width; i++) 1.4324 + { 1.4325 + *dp-- = palette[*sp].blue; 1.4326 + *dp-- = palette[*sp].green; 1.4327 + *dp-- = palette[*sp].red; 1.4328 + sp--; 1.4329 + } 1.4330 + 1.4331 + row_info->bit_depth = 8; 1.4332 + row_info->pixel_depth = 24; 1.4333 + row_info->rowbytes = row_width * 3; 1.4334 + row_info->color_type = 2; 1.4335 + row_info->channels = 3; 1.4336 + } 1.4337 + } 1.4338 + } 1.4339 + } 1.4340 +} 1.4341 + 1.4342 +/* If the bit depth < 8, it is expanded to 8. Also, if the already 1.4343 + * expanded transparency value is supplied, an alpha channel is built. 1.4344 + */ 1.4345 +static void 1.4346 +png_do_expand(png_row_infop row_info, png_bytep row, 1.4347 + png_const_color_16p trans_color) 1.4348 +{ 1.4349 + int shift, value; 1.4350 + png_bytep sp, dp; 1.4351 + png_uint_32 i; 1.4352 + png_uint_32 row_width=row_info->width; 1.4353 + 1.4354 + png_debug(1, "in png_do_expand"); 1.4355 + 1.4356 + { 1.4357 + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.4358 + { 1.4359 + unsigned int gray = trans_color ? trans_color->gray : 0; 1.4360 + 1.4361 + if (row_info->bit_depth < 8) 1.4362 + { 1.4363 + switch (row_info->bit_depth) 1.4364 + { 1.4365 + case 1: 1.4366 + { 1.4367 + gray = (gray & 0x01) * 0xff; 1.4368 + sp = row + (png_size_t)((row_width - 1) >> 3); 1.4369 + dp = row + (png_size_t)row_width - 1; 1.4370 + shift = 7 - (int)((row_width + 7) & 0x07); 1.4371 + for (i = 0; i < row_width; i++) 1.4372 + { 1.4373 + if ((*sp >> shift) & 0x01) 1.4374 + *dp = 0xff; 1.4375 + 1.4376 + else 1.4377 + *dp = 0; 1.4378 + 1.4379 + if (shift == 7) 1.4380 + { 1.4381 + shift = 0; 1.4382 + sp--; 1.4383 + } 1.4384 + 1.4385 + else 1.4386 + shift++; 1.4387 + 1.4388 + dp--; 1.4389 + } 1.4390 + break; 1.4391 + } 1.4392 + 1.4393 + case 2: 1.4394 + { 1.4395 + gray = (gray & 0x03) * 0x55; 1.4396 + sp = row + (png_size_t)((row_width - 1) >> 2); 1.4397 + dp = row + (png_size_t)row_width - 1; 1.4398 + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.4399 + for (i = 0; i < row_width; i++) 1.4400 + { 1.4401 + value = (*sp >> shift) & 0x03; 1.4402 + *dp = (png_byte)(value | (value << 2) | (value << 4) | 1.4403 + (value << 6)); 1.4404 + if (shift == 6) 1.4405 + { 1.4406 + shift = 0; 1.4407 + sp--; 1.4408 + } 1.4409 + 1.4410 + else 1.4411 + shift += 2; 1.4412 + 1.4413 + dp--; 1.4414 + } 1.4415 + break; 1.4416 + } 1.4417 + 1.4418 + case 4: 1.4419 + { 1.4420 + gray = (gray & 0x0f) * 0x11; 1.4421 + sp = row + (png_size_t)((row_width - 1) >> 1); 1.4422 + dp = row + (png_size_t)row_width - 1; 1.4423 + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 1.4424 + for (i = 0; i < row_width; i++) 1.4425 + { 1.4426 + value = (*sp >> shift) & 0x0f; 1.4427 + *dp = (png_byte)(value | (value << 4)); 1.4428 + if (shift == 4) 1.4429 + { 1.4430 + shift = 0; 1.4431 + sp--; 1.4432 + } 1.4433 + 1.4434 + else 1.4435 + shift = 4; 1.4436 + 1.4437 + dp--; 1.4438 + } 1.4439 + break; 1.4440 + } 1.4441 + 1.4442 + default: 1.4443 + break; 1.4444 + } 1.4445 + 1.4446 + row_info->bit_depth = 8; 1.4447 + row_info->pixel_depth = 8; 1.4448 + row_info->rowbytes = row_width; 1.4449 + } 1.4450 + 1.4451 + if (trans_color != NULL) 1.4452 + { 1.4453 + if (row_info->bit_depth == 8) 1.4454 + { 1.4455 + gray = gray & 0xff; 1.4456 + sp = row + (png_size_t)row_width - 1; 1.4457 + dp = row + (png_size_t)(row_width << 1) - 1; 1.4458 + 1.4459 + for (i = 0; i < row_width; i++) 1.4460 + { 1.4461 + if (*sp == gray) 1.4462 + *dp-- = 0; 1.4463 + 1.4464 + else 1.4465 + *dp-- = 0xff; 1.4466 + 1.4467 + *dp-- = *sp--; 1.4468 + } 1.4469 + } 1.4470 + 1.4471 + else if (row_info->bit_depth == 16) 1.4472 + { 1.4473 + unsigned int gray_high = (gray >> 8) & 0xff; 1.4474 + unsigned int gray_low = gray & 0xff; 1.4475 + sp = row + row_info->rowbytes - 1; 1.4476 + dp = row + (row_info->rowbytes << 1) - 1; 1.4477 + for (i = 0; i < row_width; i++) 1.4478 + { 1.4479 + if (*(sp - 1) == gray_high && *(sp) == gray_low) 1.4480 + { 1.4481 + *dp-- = 0; 1.4482 + *dp-- = 0; 1.4483 + } 1.4484 + 1.4485 + else 1.4486 + { 1.4487 + *dp-- = 0xff; 1.4488 + *dp-- = 0xff; 1.4489 + } 1.4490 + 1.4491 + *dp-- = *sp--; 1.4492 + *dp-- = *sp--; 1.4493 + } 1.4494 + } 1.4495 + 1.4496 + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 1.4497 + row_info->channels = 2; 1.4498 + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 1.4499 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 1.4500 + row_width); 1.4501 + } 1.4502 + } 1.4503 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) 1.4504 + { 1.4505 + if (row_info->bit_depth == 8) 1.4506 + { 1.4507 + png_byte red = (png_byte)(trans_color->red & 0xff); 1.4508 + png_byte green = (png_byte)(trans_color->green & 0xff); 1.4509 + png_byte blue = (png_byte)(trans_color->blue & 0xff); 1.4510 + sp = row + (png_size_t)row_info->rowbytes - 1; 1.4511 + dp = row + (png_size_t)(row_width << 2) - 1; 1.4512 + for (i = 0; i < row_width; i++) 1.4513 + { 1.4514 + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 1.4515 + *dp-- = 0; 1.4516 + 1.4517 + else 1.4518 + *dp-- = 0xff; 1.4519 + 1.4520 + *dp-- = *sp--; 1.4521 + *dp-- = *sp--; 1.4522 + *dp-- = *sp--; 1.4523 + } 1.4524 + } 1.4525 + else if (row_info->bit_depth == 16) 1.4526 + { 1.4527 + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); 1.4528 + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); 1.4529 + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); 1.4530 + png_byte red_low = (png_byte)(trans_color->red & 0xff); 1.4531 + png_byte green_low = (png_byte)(trans_color->green & 0xff); 1.4532 + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); 1.4533 + sp = row + row_info->rowbytes - 1; 1.4534 + dp = row + (png_size_t)(row_width << 3) - 1; 1.4535 + for (i = 0; i < row_width; i++) 1.4536 + { 1.4537 + if (*(sp - 5) == red_high && 1.4538 + *(sp - 4) == red_low && 1.4539 + *(sp - 3) == green_high && 1.4540 + *(sp - 2) == green_low && 1.4541 + *(sp - 1) == blue_high && 1.4542 + *(sp ) == blue_low) 1.4543 + { 1.4544 + *dp-- = 0; 1.4545 + *dp-- = 0; 1.4546 + } 1.4547 + 1.4548 + else 1.4549 + { 1.4550 + *dp-- = 0xff; 1.4551 + *dp-- = 0xff; 1.4552 + } 1.4553 + 1.4554 + *dp-- = *sp--; 1.4555 + *dp-- = *sp--; 1.4556 + *dp-- = *sp--; 1.4557 + *dp-- = *sp--; 1.4558 + *dp-- = *sp--; 1.4559 + *dp-- = *sp--; 1.4560 + } 1.4561 + } 1.4562 + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1.4563 + row_info->channels = 4; 1.4564 + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 1.4565 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.4566 + } 1.4567 + } 1.4568 +} 1.4569 +#endif 1.4570 + 1.4571 +#ifdef PNG_READ_EXPAND_16_SUPPORTED 1.4572 +/* If the bit depth is 8 and the color type is not a palette type expand the 1.4573 + * whole row to 16 bits. Has no effect otherwise. 1.4574 + */ 1.4575 +static void 1.4576 +png_do_expand_16(png_row_infop row_info, png_bytep row) 1.4577 +{ 1.4578 + if (row_info->bit_depth == 8 && 1.4579 + row_info->color_type != PNG_COLOR_TYPE_PALETTE) 1.4580 + { 1.4581 + /* The row have a sequence of bytes containing [0..255] and we need 1.4582 + * to turn it into another row containing [0..65535], to do this we 1.4583 + * calculate: 1.4584 + * 1.4585 + * (input / 255) * 65535 1.4586 + * 1.4587 + * Which happens to be exactly input * 257 and this can be achieved 1.4588 + * simply by byte replication in place (copying backwards). 1.4589 + */ 1.4590 + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ 1.4591 + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ 1.4592 + while (dp > sp) 1.4593 + dp[-2] = dp[-1] = *--sp, dp -= 2; 1.4594 + 1.4595 + row_info->rowbytes *= 2; 1.4596 + row_info->bit_depth = 16; 1.4597 + row_info->pixel_depth = (png_byte)(row_info->channels * 16); 1.4598 + } 1.4599 +} 1.4600 +#endif 1.4601 + 1.4602 +#ifdef PNG_READ_QUANTIZE_SUPPORTED 1.4603 +static void 1.4604 +png_do_quantize(png_row_infop row_info, png_bytep row, 1.4605 + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) 1.4606 +{ 1.4607 + png_bytep sp, dp; 1.4608 + png_uint_32 i; 1.4609 + png_uint_32 row_width=row_info->width; 1.4610 + 1.4611 + png_debug(1, "in png_do_quantize"); 1.4612 + 1.4613 + if (row_info->bit_depth == 8) 1.4614 + { 1.4615 + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) 1.4616 + { 1.4617 + int r, g, b, p; 1.4618 + sp = row; 1.4619 + dp = row; 1.4620 + for (i = 0; i < row_width; i++) 1.4621 + { 1.4622 + r = *sp++; 1.4623 + g = *sp++; 1.4624 + b = *sp++; 1.4625 + 1.4626 + /* This looks real messy, but the compiler will reduce 1.4627 + * it down to a reasonable formula. For example, with 1.4628 + * 5 bits per color, we get: 1.4629 + * p = (((r >> 3) & 0x1f) << 10) | 1.4630 + * (((g >> 3) & 0x1f) << 5) | 1.4631 + * ((b >> 3) & 0x1f); 1.4632 + */ 1.4633 + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 1.4634 + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 1.4635 + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 1.4636 + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 1.4637 + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 1.4638 + (PNG_QUANTIZE_BLUE_BITS)) | 1.4639 + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 1.4640 + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 1.4641 + 1.4642 + *dp++ = palette_lookup[p]; 1.4643 + } 1.4644 + 1.4645 + row_info->color_type = PNG_COLOR_TYPE_PALETTE; 1.4646 + row_info->channels = 1; 1.4647 + row_info->pixel_depth = row_info->bit_depth; 1.4648 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.4649 + } 1.4650 + 1.4651 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 1.4652 + palette_lookup != NULL) 1.4653 + { 1.4654 + int r, g, b, p; 1.4655 + sp = row; 1.4656 + dp = row; 1.4657 + for (i = 0; i < row_width; i++) 1.4658 + { 1.4659 + r = *sp++; 1.4660 + g = *sp++; 1.4661 + b = *sp++; 1.4662 + sp++; 1.4663 + 1.4664 + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 1.4665 + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 1.4666 + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 1.4667 + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 1.4668 + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 1.4669 + (PNG_QUANTIZE_BLUE_BITS)) | 1.4670 + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 1.4671 + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 1.4672 + 1.4673 + *dp++ = palette_lookup[p]; 1.4674 + } 1.4675 + 1.4676 + row_info->color_type = PNG_COLOR_TYPE_PALETTE; 1.4677 + row_info->channels = 1; 1.4678 + row_info->pixel_depth = row_info->bit_depth; 1.4679 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.4680 + } 1.4681 + 1.4682 + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 1.4683 + quantize_lookup) 1.4684 + { 1.4685 + sp = row; 1.4686 + 1.4687 + for (i = 0; i < row_width; i++, sp++) 1.4688 + { 1.4689 + *sp = quantize_lookup[*sp]; 1.4690 + } 1.4691 + } 1.4692 + } 1.4693 +} 1.4694 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ 1.4695 + 1.4696 +/* Transform the row. The order of transformations is significant, 1.4697 + * and is very touchy. If you add a transformation, take care to 1.4698 + * decide how it fits in with the other transformations here. 1.4699 + */ 1.4700 +void /* PRIVATE */ 1.4701 +png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) 1.4702 +{ 1.4703 + png_debug(1, "in png_do_read_transformations"); 1.4704 + 1.4705 + if (png_ptr->row_buf == NULL) 1.4706 + { 1.4707 + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this 1.4708 + * error is incredibly rare and incredibly easy to debug without this 1.4709 + * information. 1.4710 + */ 1.4711 + png_error(png_ptr, "NULL row buffer"); 1.4712 + } 1.4713 + 1.4714 + /* The following is debugging; prior to 1.5.4 the code was never compiled in; 1.4715 + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro 1.4716 + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for 1.4717 + * all transformations, however in practice the ROW_INIT always gets done on 1.4718 + * demand, if necessary. 1.4719 + */ 1.4720 + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && 1.4721 + !(png_ptr->flags & PNG_FLAG_ROW_INIT)) 1.4722 + { 1.4723 + /* Application has failed to call either png_read_start_image() or 1.4724 + * png_read_update_info() after setting transforms that expand pixels. 1.4725 + * This check added to libpng-1.2.19 (but not enabled until 1.5.4). 1.4726 + */ 1.4727 + png_error(png_ptr, "Uninitialized row"); 1.4728 + } 1.4729 + 1.4730 +#ifdef PNG_READ_EXPAND_SUPPORTED 1.4731 + if (png_ptr->transformations & PNG_EXPAND) 1.4732 + { 1.4733 + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 1.4734 + { 1.4735 + png_do_expand_palette(row_info, png_ptr->row_buf + 1, 1.4736 + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); 1.4737 + } 1.4738 + 1.4739 + else 1.4740 + { 1.4741 + if (png_ptr->num_trans && 1.4742 + (png_ptr->transformations & PNG_EXPAND_tRNS)) 1.4743 + png_do_expand(row_info, png_ptr->row_buf + 1, 1.4744 + &(png_ptr->trans_color)); 1.4745 + 1.4746 + else 1.4747 + png_do_expand(row_info, png_ptr->row_buf + 1, 1.4748 + NULL); 1.4749 + } 1.4750 + } 1.4751 +#endif 1.4752 + 1.4753 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1.4754 + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 1.4755 + !(png_ptr->transformations & PNG_COMPOSE) && 1.4756 + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 1.4757 + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 1.4758 + png_do_strip_channel(row_info, png_ptr->row_buf + 1, 1.4759 + 0 /* at_start == false, because SWAP_ALPHA happens later */); 1.4760 +#endif 1.4761 + 1.4762 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.4763 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.4764 + { 1.4765 + int rgb_error = 1.4766 + png_do_rgb_to_gray(png_ptr, row_info, 1.4767 + png_ptr->row_buf + 1); 1.4768 + 1.4769 + if (rgb_error) 1.4770 + { 1.4771 + png_ptr->rgb_to_gray_status=1; 1.4772 + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1.4773 + PNG_RGB_TO_GRAY_WARN) 1.4774 + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1.4775 + 1.4776 + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1.4777 + PNG_RGB_TO_GRAY_ERR) 1.4778 + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1.4779 + } 1.4780 + } 1.4781 +#endif 1.4782 + 1.4783 +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: 1.4784 + * 1.4785 + * In most cases, the "simple transparency" should be done prior to doing 1.4786 + * gray-to-RGB, or you will have to test 3x as many bytes to check if a 1.4787 + * pixel is transparent. You would also need to make sure that the 1.4788 + * transparency information is upgraded to RGB. 1.4789 + * 1.4790 + * To summarize, the current flow is: 1.4791 + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 1.4792 + * with background "in place" if transparent, 1.4793 + * convert to RGB if necessary 1.4794 + * - Gray + alpha -> composite with gray background and remove alpha bytes, 1.4795 + * convert to RGB if necessary 1.4796 + * 1.4797 + * To support RGB backgrounds for gray images we need: 1.4798 + * - Gray + simple transparency -> convert to RGB + simple transparency, 1.4799 + * compare 3 or 6 bytes and composite with 1.4800 + * background "in place" if transparent 1.4801 + * (3x compare/pixel compared to doing 1.4802 + * composite with gray bkgrnd) 1.4803 + * - Gray + alpha -> convert to RGB + alpha, composite with background and 1.4804 + * remove alpha bytes (3x float 1.4805 + * operations/pixel compared with composite 1.4806 + * on gray background) 1.4807 + * 1.4808 + * Greg's change will do this. The reason it wasn't done before is for 1.4809 + * performance, as this increases the per-pixel operations. If we would check 1.4810 + * in advance if the background was gray or RGB, and position the gray-to-RGB 1.4811 + * transform appropriately, then it would save a lot of work/time. 1.4812 + */ 1.4813 + 1.4814 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.4815 + /* If gray -> RGB, do so now only if background is non-gray; else do later 1.4816 + * for performance reasons 1.4817 + */ 1.4818 + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1.4819 + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1.4820 + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 1.4821 +#endif 1.4822 + 1.4823 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 1.4824 + defined(PNG_READ_ALPHA_MODE_SUPPORTED) 1.4825 + if (png_ptr->transformations & PNG_COMPOSE) 1.4826 + png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); 1.4827 +#endif 1.4828 + 1.4829 +#ifdef PNG_READ_GAMMA_SUPPORTED 1.4830 + if ((png_ptr->transformations & PNG_GAMMA) && 1.4831 +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1.4832 + /* Because RGB_TO_GRAY does the gamma transform. */ 1.4833 + !(png_ptr->transformations & PNG_RGB_TO_GRAY) && 1.4834 +#endif 1.4835 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 1.4836 + defined(PNG_READ_ALPHA_MODE_SUPPORTED) 1.4837 + /* Because PNG_COMPOSE does the gamma transform if there is something to 1.4838 + * do (if there is an alpha channel or transparency.) 1.4839 + */ 1.4840 + !((png_ptr->transformations & PNG_COMPOSE) && 1.4841 + ((png_ptr->num_trans != 0) || 1.4842 + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && 1.4843 +#endif 1.4844 + /* Because png_init_read_transformations transforms the palette, unless 1.4845 + * RGB_TO_GRAY will do the transform. 1.4846 + */ 1.4847 + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 1.4848 + png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); 1.4849 +#endif 1.4850 + 1.4851 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1.4852 + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 1.4853 + (png_ptr->transformations & PNG_COMPOSE) && 1.4854 + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 1.4855 + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 1.4856 + png_do_strip_channel(row_info, png_ptr->row_buf + 1, 1.4857 + 0 /* at_start == false, because SWAP_ALPHA happens later */); 1.4858 +#endif 1.4859 + 1.4860 +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1.4861 + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && 1.4862 + (row_info->color_type & PNG_COLOR_MASK_ALPHA)) 1.4863 + png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); 1.4864 +#endif 1.4865 + 1.4866 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1.4867 + if (png_ptr->transformations & PNG_SCALE_16_TO_8) 1.4868 + png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); 1.4869 +#endif 1.4870 + 1.4871 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1.4872 + /* There is no harm in doing both of these because only one has any effect, 1.4873 + * by putting the 'scale' option first if the app asks for scale (either by 1.4874 + * calling the API or in a TRANSFORM flag) this is what happens. 1.4875 + */ 1.4876 + if (png_ptr->transformations & PNG_16_TO_8) 1.4877 + png_do_chop(row_info, png_ptr->row_buf + 1); 1.4878 +#endif 1.4879 + 1.4880 +#ifdef PNG_READ_QUANTIZE_SUPPORTED 1.4881 + if (png_ptr->transformations & PNG_QUANTIZE) 1.4882 + { 1.4883 + png_do_quantize(row_info, png_ptr->row_buf + 1, 1.4884 + png_ptr->palette_lookup, png_ptr->quantize_index); 1.4885 + 1.4886 + if (row_info->rowbytes == 0) 1.4887 + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); 1.4888 + } 1.4889 +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ 1.4890 + 1.4891 +#ifdef PNG_READ_EXPAND_16_SUPPORTED 1.4892 + /* Do the expansion now, after all the arithmetic has been done. Notice 1.4893 + * that previous transformations can handle the PNG_EXPAND_16 flag if this 1.4894 + * is efficient (particularly true in the case of gamma correction, where 1.4895 + * better accuracy results faster!) 1.4896 + */ 1.4897 + if (png_ptr->transformations & PNG_EXPAND_16) 1.4898 + png_do_expand_16(row_info, png_ptr->row_buf + 1); 1.4899 +#endif 1.4900 + 1.4901 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1.4902 + /* NOTE: moved here in 1.5.4 (from much later in this list.) */ 1.4903 + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1.4904 + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1.4905 + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 1.4906 +#endif 1.4907 + 1.4908 +#ifdef PNG_READ_INVERT_SUPPORTED 1.4909 + if (png_ptr->transformations & PNG_INVERT_MONO) 1.4910 + png_do_invert(row_info, png_ptr->row_buf + 1); 1.4911 +#endif 1.4912 + 1.4913 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1.4914 + if (png_ptr->transformations & PNG_INVERT_ALPHA) 1.4915 + png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); 1.4916 +#endif 1.4917 + 1.4918 +#ifdef PNG_READ_SHIFT_SUPPORTED 1.4919 + if (png_ptr->transformations & PNG_SHIFT) 1.4920 + png_do_unshift(row_info, png_ptr->row_buf + 1, 1.4921 + &(png_ptr->shift)); 1.4922 +#endif 1.4923 + 1.4924 +#ifdef PNG_READ_PACK_SUPPORTED 1.4925 + if (png_ptr->transformations & PNG_PACK) 1.4926 + png_do_unpack(row_info, png_ptr->row_buf + 1); 1.4927 +#endif 1.4928 + 1.4929 +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED 1.4930 + /* Added at libpng-1.5.10 */ 1.4931 + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 1.4932 + png_ptr->num_palette_max >= 0) 1.4933 + png_do_check_palette_indexes(png_ptr, row_info); 1.4934 +#endif 1.4935 + 1.4936 +#ifdef PNG_READ_BGR_SUPPORTED 1.4937 + if (png_ptr->transformations & PNG_BGR) 1.4938 + png_do_bgr(row_info, png_ptr->row_buf + 1); 1.4939 +#endif 1.4940 + 1.4941 +#ifdef PNG_READ_PACKSWAP_SUPPORTED 1.4942 + if (png_ptr->transformations & PNG_PACKSWAP) 1.4943 + png_do_packswap(row_info, png_ptr->row_buf + 1); 1.4944 +#endif 1.4945 + 1.4946 +#ifdef PNG_READ_FILLER_SUPPORTED 1.4947 + if (png_ptr->transformations & PNG_FILLER) 1.4948 + png_do_read_filler(row_info, png_ptr->row_buf + 1, 1.4949 + (png_uint_32)png_ptr->filler, png_ptr->flags); 1.4950 +#endif 1.4951 + 1.4952 +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1.4953 + if (png_ptr->transformations & PNG_SWAP_ALPHA) 1.4954 + png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); 1.4955 +#endif 1.4956 + 1.4957 +#ifdef PNG_READ_16BIT_SUPPORTED 1.4958 +#ifdef PNG_READ_SWAP_SUPPORTED 1.4959 + if (png_ptr->transformations & PNG_SWAP_BYTES) 1.4960 + png_do_swap(row_info, png_ptr->row_buf + 1); 1.4961 +#endif 1.4962 +#endif 1.4963 + 1.4964 +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1.4965 + if (png_ptr->transformations & PNG_USER_TRANSFORM) 1.4966 + { 1.4967 + if (png_ptr->read_user_transform_fn != NULL) 1.4968 + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ 1.4969 + (png_ptr, /* png_ptr */ 1.4970 + row_info, /* row_info: */ 1.4971 + /* png_uint_32 width; width of row */ 1.4972 + /* png_size_t rowbytes; number of bytes in row */ 1.4973 + /* png_byte color_type; color type of pixels */ 1.4974 + /* png_byte bit_depth; bit depth of samples */ 1.4975 + /* png_byte channels; number of channels (1-4) */ 1.4976 + /* png_byte pixel_depth; bits per pixel (depth*channels) */ 1.4977 + png_ptr->row_buf + 1); /* start of pixel data for row */ 1.4978 +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED 1.4979 + if (png_ptr->user_transform_depth) 1.4980 + row_info->bit_depth = png_ptr->user_transform_depth; 1.4981 + 1.4982 + if (png_ptr->user_transform_channels) 1.4983 + row_info->channels = png_ptr->user_transform_channels; 1.4984 +#endif 1.4985 + row_info->pixel_depth = (png_byte)(row_info->bit_depth * 1.4986 + row_info->channels); 1.4987 + 1.4988 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); 1.4989 + } 1.4990 +#endif 1.4991 +} 1.4992 + 1.4993 +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 1.4994 +#endif /* PNG_READ_SUPPORTED */