1*c2c66affSColin Finck 2*c2c66affSColin Finck /* pngrtran.c - transforms the data in a row for PNG readers 3*c2c66affSColin Finck * 4*c2c66affSColin Finck * Last changed in libpng 1.6.31 [July 27, 2017] 5*c2c66affSColin Finck * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson 6*c2c66affSColin Finck * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7*c2c66affSColin Finck * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8*c2c66affSColin Finck * 9*c2c66affSColin Finck * This code is released under the libpng license. 10*c2c66affSColin Finck * For conditions of distribution and use, see the disclaimer 11*c2c66affSColin Finck * and license in png.h 12*c2c66affSColin Finck * 13*c2c66affSColin Finck * This file contains functions optionally called by an application 14*c2c66affSColin Finck * in order to tell libpng how to handle data when reading a PNG. 15*c2c66affSColin Finck * Transformations that are used in both reading and writing are 16*c2c66affSColin Finck * in pngtrans.c. 17*c2c66affSColin Finck */ 18*c2c66affSColin Finck 19*c2c66affSColin Finck #include "pngpriv.h" 20*c2c66affSColin Finck 21*c2c66affSColin Finck #ifdef PNG_READ_SUPPORTED 22*c2c66affSColin Finck 23*c2c66affSColin Finck /* Set the action on getting a CRC error for an ancillary or critical chunk. */ 24*c2c66affSColin Finck void PNGAPI 25*c2c66affSColin Finck png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) 26*c2c66affSColin Finck { 27*c2c66affSColin Finck png_debug(1, "in png_set_crc_action"); 28*c2c66affSColin Finck 29*c2c66affSColin Finck if (png_ptr == NULL) 30*c2c66affSColin Finck return; 31*c2c66affSColin Finck 32*c2c66affSColin Finck /* Tell libpng how we react to CRC errors in critical chunks */ 33*c2c66affSColin Finck switch (crit_action) 34*c2c66affSColin Finck { 35*c2c66affSColin Finck case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 36*c2c66affSColin Finck break; 37*c2c66affSColin Finck 38*c2c66affSColin Finck case PNG_CRC_WARN_USE: /* Warn/use data */ 39*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 40*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 41*c2c66affSColin Finck break; 42*c2c66affSColin Finck 43*c2c66affSColin Finck case PNG_CRC_QUIET_USE: /* Quiet/use data */ 44*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 45*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 46*c2c66affSColin Finck PNG_FLAG_CRC_CRITICAL_IGNORE; 47*c2c66affSColin Finck break; 48*c2c66affSColin Finck 49*c2c66affSColin Finck case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ 50*c2c66affSColin Finck png_warning(png_ptr, 51*c2c66affSColin Finck "Can't discard critical data on CRC error"); 52*c2c66affSColin Finck /* FALLTHROUGH */ 53*c2c66affSColin Finck case PNG_CRC_ERROR_QUIT: /* Error/quit */ 54*c2c66affSColin Finck 55*c2c66affSColin Finck case PNG_CRC_DEFAULT: 56*c2c66affSColin Finck default: 57*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 58*c2c66affSColin Finck break; 59*c2c66affSColin Finck } 60*c2c66affSColin Finck 61*c2c66affSColin Finck /* Tell libpng how we react to CRC errors in ancillary chunks */ 62*c2c66affSColin Finck switch (ancil_action) 63*c2c66affSColin Finck { 64*c2c66affSColin Finck case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 65*c2c66affSColin Finck break; 66*c2c66affSColin Finck 67*c2c66affSColin Finck case PNG_CRC_WARN_USE: /* Warn/use data */ 68*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 69*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 70*c2c66affSColin Finck break; 71*c2c66affSColin Finck 72*c2c66affSColin Finck case PNG_CRC_QUIET_USE: /* Quiet/use data */ 73*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 74*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 75*c2c66affSColin Finck PNG_FLAG_CRC_ANCILLARY_NOWARN; 76*c2c66affSColin Finck break; 77*c2c66affSColin Finck 78*c2c66affSColin Finck case PNG_CRC_ERROR_QUIT: /* Error/quit */ 79*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 80*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 81*c2c66affSColin Finck break; 82*c2c66affSColin Finck 83*c2c66affSColin Finck case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ 84*c2c66affSColin Finck 85*c2c66affSColin Finck case PNG_CRC_DEFAULT: 86*c2c66affSColin Finck default: 87*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 88*c2c66affSColin Finck break; 89*c2c66affSColin Finck } 90*c2c66affSColin Finck } 91*c2c66affSColin Finck 92*c2c66affSColin Finck #ifdef PNG_READ_TRANSFORMS_SUPPORTED 93*c2c66affSColin Finck /* Is it OK to set a transformation now? Only if png_start_read_image or 94*c2c66affSColin Finck * png_read_update_info have not been called. It is not necessary for the IHDR 95*c2c66affSColin Finck * to have been read in all cases; the need_IHDR parameter allows for this 96*c2c66affSColin Finck * check too. 97*c2c66affSColin Finck */ 98*c2c66affSColin Finck static int 99*c2c66affSColin Finck png_rtran_ok(png_structrp png_ptr, int need_IHDR) 100*c2c66affSColin Finck { 101*c2c66affSColin Finck if (png_ptr != NULL) 102*c2c66affSColin Finck { 103*c2c66affSColin Finck if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) 104*c2c66affSColin Finck png_app_error(png_ptr, 105*c2c66affSColin Finck "invalid after png_start_read_image or png_read_update_info"); 106*c2c66affSColin Finck 107*c2c66affSColin Finck else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) 108*c2c66affSColin Finck png_app_error(png_ptr, "invalid before the PNG header has been read"); 109*c2c66affSColin Finck 110*c2c66affSColin Finck else 111*c2c66affSColin Finck { 112*c2c66affSColin Finck /* Turn on failure to initialize correctly for all transforms. */ 113*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; 114*c2c66affSColin Finck 115*c2c66affSColin Finck return 1; /* Ok */ 116*c2c66affSColin Finck } 117*c2c66affSColin Finck } 118*c2c66affSColin Finck 119*c2c66affSColin Finck return 0; /* no png_error possible! */ 120*c2c66affSColin Finck } 121*c2c66affSColin Finck #endif 122*c2c66affSColin Finck 123*c2c66affSColin Finck #ifdef PNG_READ_BACKGROUND_SUPPORTED 124*c2c66affSColin Finck /* Handle alpha and tRNS via a background color */ 125*c2c66affSColin Finck void PNGFAPI 126*c2c66affSColin Finck png_set_background_fixed(png_structrp png_ptr, 127*c2c66affSColin Finck png_const_color_16p background_color, int background_gamma_code, 128*c2c66affSColin Finck int need_expand, png_fixed_point background_gamma) 129*c2c66affSColin Finck { 130*c2c66affSColin Finck png_debug(1, "in png_set_background_fixed"); 131*c2c66affSColin Finck 132*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL) 133*c2c66affSColin Finck return; 134*c2c66affSColin Finck 135*c2c66affSColin Finck if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 136*c2c66affSColin Finck { 137*c2c66affSColin Finck png_warning(png_ptr, "Application must supply a known background gamma"); 138*c2c66affSColin Finck return; 139*c2c66affSColin Finck } 140*c2c66affSColin Finck 141*c2c66affSColin Finck png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; 142*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 143*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 144*c2c66affSColin Finck 145*c2c66affSColin Finck png_ptr->background = *background_color; 146*c2c66affSColin Finck png_ptr->background_gamma = background_gamma; 147*c2c66affSColin Finck png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 148*c2c66affSColin Finck if (need_expand != 0) 149*c2c66affSColin Finck png_ptr->transformations |= PNG_BACKGROUND_EXPAND; 150*c2c66affSColin Finck else 151*c2c66affSColin Finck png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 152*c2c66affSColin Finck } 153*c2c66affSColin Finck 154*c2c66affSColin Finck # ifdef PNG_FLOATING_POINT_SUPPORTED 155*c2c66affSColin Finck void PNGAPI 156*c2c66affSColin Finck png_set_background(png_structrp png_ptr, 157*c2c66affSColin Finck png_const_color_16p background_color, int background_gamma_code, 158*c2c66affSColin Finck int need_expand, double background_gamma) 159*c2c66affSColin Finck { 160*c2c66affSColin Finck png_set_background_fixed(png_ptr, background_color, background_gamma_code, 161*c2c66affSColin Finck need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); 162*c2c66affSColin Finck } 163*c2c66affSColin Finck # endif /* FLOATING_POINT */ 164*c2c66affSColin Finck #endif /* READ_BACKGROUND */ 165*c2c66affSColin Finck 166*c2c66affSColin Finck /* Scale 16-bit depth files to 8-bit depth. If both of these are set then the 167*c2c66affSColin Finck * one that pngrtran does first (scale) happens. This is necessary to allow the 168*c2c66affSColin Finck * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. 169*c2c66affSColin Finck */ 170*c2c66affSColin Finck #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 171*c2c66affSColin Finck void PNGAPI 172*c2c66affSColin Finck png_set_scale_16(png_structrp png_ptr) 173*c2c66affSColin Finck { 174*c2c66affSColin Finck png_debug(1, "in png_set_scale_16"); 175*c2c66affSColin Finck 176*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 177*c2c66affSColin Finck return; 178*c2c66affSColin Finck 179*c2c66affSColin Finck png_ptr->transformations |= PNG_SCALE_16_TO_8; 180*c2c66affSColin Finck } 181*c2c66affSColin Finck #endif 182*c2c66affSColin Finck 183*c2c66affSColin Finck #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 184*c2c66affSColin Finck /* Chop 16-bit depth files to 8-bit depth */ 185*c2c66affSColin Finck void PNGAPI 186*c2c66affSColin Finck png_set_strip_16(png_structrp png_ptr) 187*c2c66affSColin Finck { 188*c2c66affSColin Finck png_debug(1, "in png_set_strip_16"); 189*c2c66affSColin Finck 190*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 191*c2c66affSColin Finck return; 192*c2c66affSColin Finck 193*c2c66affSColin Finck png_ptr->transformations |= PNG_16_TO_8; 194*c2c66affSColin Finck } 195*c2c66affSColin Finck #endif 196*c2c66affSColin Finck 197*c2c66affSColin Finck #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 198*c2c66affSColin Finck void PNGAPI 199*c2c66affSColin Finck png_set_strip_alpha(png_structrp png_ptr) 200*c2c66affSColin Finck { 201*c2c66affSColin Finck png_debug(1, "in png_set_strip_alpha"); 202*c2c66affSColin Finck 203*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 204*c2c66affSColin Finck return; 205*c2c66affSColin Finck 206*c2c66affSColin Finck png_ptr->transformations |= PNG_STRIP_ALPHA; 207*c2c66affSColin Finck } 208*c2c66affSColin Finck #endif 209*c2c66affSColin Finck 210*c2c66affSColin Finck #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) 211*c2c66affSColin Finck static png_fixed_point 212*c2c66affSColin Finck translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, 213*c2c66affSColin Finck int is_screen) 214*c2c66affSColin Finck { 215*c2c66affSColin Finck /* Check for flag values. The main reason for having the old Mac value as a 216*c2c66affSColin Finck * flag is that it is pretty near impossible to work out what the correct 217*c2c66affSColin Finck * value is from Apple documentation - a working Mac system is needed to 218*c2c66affSColin Finck * discover the value! 219*c2c66affSColin Finck */ 220*c2c66affSColin Finck if (output_gamma == PNG_DEFAULT_sRGB || 221*c2c66affSColin Finck output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) 222*c2c66affSColin Finck { 223*c2c66affSColin Finck /* If there is no sRGB support this just sets the gamma to the standard 224*c2c66affSColin Finck * sRGB value. (This is a side effect of using this function!) 225*c2c66affSColin Finck */ 226*c2c66affSColin Finck # ifdef PNG_READ_sRGB_SUPPORTED 227*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; 228*c2c66affSColin Finck # else 229*c2c66affSColin Finck PNG_UNUSED(png_ptr) 230*c2c66affSColin Finck # endif 231*c2c66affSColin Finck if (is_screen != 0) 232*c2c66affSColin Finck output_gamma = PNG_GAMMA_sRGB; 233*c2c66affSColin Finck else 234*c2c66affSColin Finck output_gamma = PNG_GAMMA_sRGB_INVERSE; 235*c2c66affSColin Finck } 236*c2c66affSColin Finck 237*c2c66affSColin Finck else if (output_gamma == PNG_GAMMA_MAC_18 || 238*c2c66affSColin Finck output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) 239*c2c66affSColin Finck { 240*c2c66affSColin Finck if (is_screen != 0) 241*c2c66affSColin Finck output_gamma = PNG_GAMMA_MAC_OLD; 242*c2c66affSColin Finck else 243*c2c66affSColin Finck output_gamma = PNG_GAMMA_MAC_INVERSE; 244*c2c66affSColin Finck } 245*c2c66affSColin Finck 246*c2c66affSColin Finck return output_gamma; 247*c2c66affSColin Finck } 248*c2c66affSColin Finck 249*c2c66affSColin Finck # ifdef PNG_FLOATING_POINT_SUPPORTED 250*c2c66affSColin Finck static png_fixed_point 251*c2c66affSColin Finck convert_gamma_value(png_structrp png_ptr, double output_gamma) 252*c2c66affSColin Finck { 253*c2c66affSColin Finck /* The following silently ignores cases where fixed point (times 100,000) 254*c2c66affSColin Finck * gamma values are passed to the floating point API. This is safe and it 255*c2c66affSColin Finck * means the fixed point constants work just fine with the floating point 256*c2c66affSColin Finck * API. The alternative would just lead to undetected errors and spurious 257*c2c66affSColin Finck * bug reports. Negative values fail inside the _fixed API unless they 258*c2c66affSColin Finck * correspond to the flag values. 259*c2c66affSColin Finck */ 260*c2c66affSColin Finck if (output_gamma > 0 && output_gamma < 128) 261*c2c66affSColin Finck output_gamma *= PNG_FP_1; 262*c2c66affSColin Finck 263*c2c66affSColin Finck /* This preserves -1 and -2 exactly: */ 264*c2c66affSColin Finck output_gamma = floor(output_gamma + .5); 265*c2c66affSColin Finck 266*c2c66affSColin Finck if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) 267*c2c66affSColin Finck png_fixed_error(png_ptr, "gamma value"); 268*c2c66affSColin Finck 269*c2c66affSColin Finck return (png_fixed_point)output_gamma; 270*c2c66affSColin Finck } 271*c2c66affSColin Finck # endif 272*c2c66affSColin Finck #endif /* READ_ALPHA_MODE || READ_GAMMA */ 273*c2c66affSColin Finck 274*c2c66affSColin Finck #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 275*c2c66affSColin Finck void PNGFAPI 276*c2c66affSColin Finck png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, 277*c2c66affSColin Finck png_fixed_point output_gamma) 278*c2c66affSColin Finck { 279*c2c66affSColin Finck int compose = 0; 280*c2c66affSColin Finck png_fixed_point file_gamma; 281*c2c66affSColin Finck 282*c2c66affSColin Finck png_debug(1, "in png_set_alpha_mode"); 283*c2c66affSColin Finck 284*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 285*c2c66affSColin Finck return; 286*c2c66affSColin Finck 287*c2c66affSColin Finck output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); 288*c2c66affSColin Finck 289*c2c66affSColin Finck /* Validate the value to ensure it is in a reasonable range. The value 290*c2c66affSColin Finck * is expected to be 1 or greater, but this range test allows for some 291*c2c66affSColin Finck * viewing correction values. The intent is to weed out users of this API 292*c2c66affSColin Finck * who use the inverse of the gamma value accidentally! Since some of these 293*c2c66affSColin Finck * values are reasonable this may have to be changed: 294*c2c66affSColin Finck * 295*c2c66affSColin Finck * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit 296*c2c66affSColin Finck * gamma of 36, and its reciprocal.) 297*c2c66affSColin Finck */ 298*c2c66affSColin Finck if (output_gamma < 1000 || output_gamma > 10000000) 299*c2c66affSColin Finck png_error(png_ptr, "output gamma out of expected range"); 300*c2c66affSColin Finck 301*c2c66affSColin Finck /* The default file gamma is the inverse of the output gamma; the output 302*c2c66affSColin Finck * gamma may be changed below so get the file value first: 303*c2c66affSColin Finck */ 304*c2c66affSColin Finck file_gamma = png_reciprocal(output_gamma); 305*c2c66affSColin Finck 306*c2c66affSColin Finck /* There are really 8 possibilities here, composed of any combination 307*c2c66affSColin Finck * of: 308*c2c66affSColin Finck * 309*c2c66affSColin Finck * premultiply the color channels 310*c2c66affSColin Finck * do not encode non-opaque pixels 311*c2c66affSColin Finck * encode the alpha as well as the color channels 312*c2c66affSColin Finck * 313*c2c66affSColin Finck * The differences disappear if the input/output ('screen') gamma is 1.0, 314*c2c66affSColin Finck * because then the encoding is a no-op and there is only the choice of 315*c2c66affSColin Finck * premultiplying the color channels or not. 316*c2c66affSColin Finck * 317*c2c66affSColin Finck * png_set_alpha_mode and png_set_background interact because both use 318*c2c66affSColin Finck * png_compose to do the work. Calling both is only useful when 319*c2c66affSColin Finck * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along 320*c2c66affSColin Finck * with a default gamma value. Otherwise PNG_COMPOSE must not be set. 321*c2c66affSColin Finck */ 322*c2c66affSColin Finck switch (mode) 323*c2c66affSColin Finck { 324*c2c66affSColin Finck case PNG_ALPHA_PNG: /* default: png standard */ 325*c2c66affSColin Finck /* No compose, but it may be set by png_set_background! */ 326*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 327*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 328*c2c66affSColin Finck break; 329*c2c66affSColin Finck 330*c2c66affSColin Finck case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ 331*c2c66affSColin Finck compose = 1; 332*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 333*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 334*c2c66affSColin Finck /* The output is linear: */ 335*c2c66affSColin Finck output_gamma = PNG_FP_1; 336*c2c66affSColin Finck break; 337*c2c66affSColin Finck 338*c2c66affSColin Finck case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ 339*c2c66affSColin Finck compose = 1; 340*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 341*c2c66affSColin Finck png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; 342*c2c66affSColin Finck /* output_gamma records the encoding of opaque pixels! */ 343*c2c66affSColin Finck break; 344*c2c66affSColin Finck 345*c2c66affSColin Finck case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ 346*c2c66affSColin Finck compose = 1; 347*c2c66affSColin Finck png_ptr->transformations |= PNG_ENCODE_ALPHA; 348*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 349*c2c66affSColin Finck break; 350*c2c66affSColin Finck 351*c2c66affSColin Finck default: 352*c2c66affSColin Finck png_error(png_ptr, "invalid alpha mode"); 353*c2c66affSColin Finck } 354*c2c66affSColin Finck 355*c2c66affSColin Finck /* Only set the default gamma if the file gamma has not been set (this has 356*c2c66affSColin Finck * the side effect that the gamma in a second call to png_set_alpha_mode will 357*c2c66affSColin Finck * be ignored.) 358*c2c66affSColin Finck */ 359*c2c66affSColin Finck if (png_ptr->colorspace.gamma == 0) 360*c2c66affSColin Finck { 361*c2c66affSColin Finck png_ptr->colorspace.gamma = file_gamma; 362*c2c66affSColin Finck png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 363*c2c66affSColin Finck } 364*c2c66affSColin Finck 365*c2c66affSColin Finck /* But always set the output gamma: */ 366*c2c66affSColin Finck png_ptr->screen_gamma = output_gamma; 367*c2c66affSColin Finck 368*c2c66affSColin Finck /* Finally, if pre-multiplying, set the background fields to achieve the 369*c2c66affSColin Finck * desired result. 370*c2c66affSColin Finck */ 371*c2c66affSColin Finck if (compose != 0) 372*c2c66affSColin Finck { 373*c2c66affSColin Finck /* And obtain alpha pre-multiplication by composing on black: */ 374*c2c66affSColin Finck memset(&png_ptr->background, 0, (sizeof png_ptr->background)); 375*c2c66affSColin Finck png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ 376*c2c66affSColin Finck png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; 377*c2c66affSColin Finck png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 378*c2c66affSColin Finck 379*c2c66affSColin Finck if ((png_ptr->transformations & PNG_COMPOSE) != 0) 380*c2c66affSColin Finck png_error(png_ptr, 381*c2c66affSColin Finck "conflicting calls to set alpha mode and background"); 382*c2c66affSColin Finck 383*c2c66affSColin Finck png_ptr->transformations |= PNG_COMPOSE; 384*c2c66affSColin Finck } 385*c2c66affSColin Finck } 386*c2c66affSColin Finck 387*c2c66affSColin Finck # ifdef PNG_FLOATING_POINT_SUPPORTED 388*c2c66affSColin Finck void PNGAPI 389*c2c66affSColin Finck png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) 390*c2c66affSColin Finck { 391*c2c66affSColin Finck png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, 392*c2c66affSColin Finck output_gamma)); 393*c2c66affSColin Finck } 394*c2c66affSColin Finck # endif 395*c2c66affSColin Finck #endif 396*c2c66affSColin Finck 397*c2c66affSColin Finck #ifdef PNG_READ_QUANTIZE_SUPPORTED 398*c2c66affSColin Finck /* Dither file to 8-bit. Supply a palette, the current number 399*c2c66affSColin Finck * of elements in the palette, the maximum number of elements 400*c2c66affSColin Finck * allowed, and a histogram if possible. If the current number 401*c2c66affSColin Finck * of colors is greater than the maximum number, the palette will be 402*c2c66affSColin Finck * modified to fit in the maximum number. "full_quantize" indicates 403*c2c66affSColin Finck * whether we need a quantizing cube set up for RGB images, or if we 404*c2c66affSColin Finck * simply are reducing the number of colors in a paletted image. 405*c2c66affSColin Finck */ 406*c2c66affSColin Finck 407*c2c66affSColin Finck typedef struct png_dsort_struct 408*c2c66affSColin Finck { 409*c2c66affSColin Finck struct png_dsort_struct * next; 410*c2c66affSColin Finck png_byte left; 411*c2c66affSColin Finck png_byte right; 412*c2c66affSColin Finck } png_dsort; 413*c2c66affSColin Finck typedef png_dsort * png_dsortp; 414*c2c66affSColin Finck typedef png_dsort * * png_dsortpp; 415*c2c66affSColin Finck 416*c2c66affSColin Finck void PNGAPI 417*c2c66affSColin Finck png_set_quantize(png_structrp png_ptr, png_colorp palette, 418*c2c66affSColin Finck int num_palette, int maximum_colors, png_const_uint_16p histogram, 419*c2c66affSColin Finck int full_quantize) 420*c2c66affSColin Finck { 421*c2c66affSColin Finck png_debug(1, "in png_set_quantize"); 422*c2c66affSColin Finck 423*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 424*c2c66affSColin Finck return; 425*c2c66affSColin Finck 426*c2c66affSColin Finck png_ptr->transformations |= PNG_QUANTIZE; 427*c2c66affSColin Finck 428*c2c66affSColin Finck if (full_quantize == 0) 429*c2c66affSColin Finck { 430*c2c66affSColin Finck int i; 431*c2c66affSColin Finck 432*c2c66affSColin Finck png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, 433*c2c66affSColin Finck (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); 434*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 435*c2c66affSColin Finck png_ptr->quantize_index[i] = (png_byte)i; 436*c2c66affSColin Finck } 437*c2c66affSColin Finck 438*c2c66affSColin Finck if (num_palette > maximum_colors) 439*c2c66affSColin Finck { 440*c2c66affSColin Finck if (histogram != NULL) 441*c2c66affSColin Finck { 442*c2c66affSColin Finck /* This is easy enough, just throw out the least used colors. 443*c2c66affSColin Finck * Perhaps not the best solution, but good enough. 444*c2c66affSColin Finck */ 445*c2c66affSColin Finck 446*c2c66affSColin Finck int i; 447*c2c66affSColin Finck 448*c2c66affSColin Finck /* Initialize an array to sort colors */ 449*c2c66affSColin Finck png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, 450*c2c66affSColin Finck (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); 451*c2c66affSColin Finck 452*c2c66affSColin Finck /* Initialize the quantize_sort array */ 453*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 454*c2c66affSColin Finck png_ptr->quantize_sort[i] = (png_byte)i; 455*c2c66affSColin Finck 456*c2c66affSColin Finck /* Find the least used palette entries by starting a 457*c2c66affSColin Finck * bubble sort, and running it until we have sorted 458*c2c66affSColin Finck * out enough colors. Note that we don't care about 459*c2c66affSColin Finck * sorting all the colors, just finding which are 460*c2c66affSColin Finck * least used. 461*c2c66affSColin Finck */ 462*c2c66affSColin Finck 463*c2c66affSColin Finck for (i = num_palette - 1; i >= maximum_colors; i--) 464*c2c66affSColin Finck { 465*c2c66affSColin Finck int done; /* To stop early if the list is pre-sorted */ 466*c2c66affSColin Finck int j; 467*c2c66affSColin Finck 468*c2c66affSColin Finck done = 1; 469*c2c66affSColin Finck for (j = 0; j < i; j++) 470*c2c66affSColin Finck { 471*c2c66affSColin Finck if (histogram[png_ptr->quantize_sort[j]] 472*c2c66affSColin Finck < histogram[png_ptr->quantize_sort[j + 1]]) 473*c2c66affSColin Finck { 474*c2c66affSColin Finck png_byte t; 475*c2c66affSColin Finck 476*c2c66affSColin Finck t = png_ptr->quantize_sort[j]; 477*c2c66affSColin Finck png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; 478*c2c66affSColin Finck png_ptr->quantize_sort[j + 1] = t; 479*c2c66affSColin Finck done = 0; 480*c2c66affSColin Finck } 481*c2c66affSColin Finck } 482*c2c66affSColin Finck 483*c2c66affSColin Finck if (done != 0) 484*c2c66affSColin Finck break; 485*c2c66affSColin Finck } 486*c2c66affSColin Finck 487*c2c66affSColin Finck /* Swap the palette around, and set up a table, if necessary */ 488*c2c66affSColin Finck if (full_quantize != 0) 489*c2c66affSColin Finck { 490*c2c66affSColin Finck int j = num_palette; 491*c2c66affSColin Finck 492*c2c66affSColin Finck /* Put all the useful colors within the max, but don't 493*c2c66affSColin Finck * move the others. 494*c2c66affSColin Finck */ 495*c2c66affSColin Finck for (i = 0; i < maximum_colors; i++) 496*c2c66affSColin Finck { 497*c2c66affSColin Finck if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 498*c2c66affSColin Finck { 499*c2c66affSColin Finck do 500*c2c66affSColin Finck j--; 501*c2c66affSColin Finck while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 502*c2c66affSColin Finck 503*c2c66affSColin Finck palette[i] = palette[j]; 504*c2c66affSColin Finck } 505*c2c66affSColin Finck } 506*c2c66affSColin Finck } 507*c2c66affSColin Finck else 508*c2c66affSColin Finck { 509*c2c66affSColin Finck int j = num_palette; 510*c2c66affSColin Finck 511*c2c66affSColin Finck /* Move all the used colors inside the max limit, and 512*c2c66affSColin Finck * develop a translation table. 513*c2c66affSColin Finck */ 514*c2c66affSColin Finck for (i = 0; i < maximum_colors; i++) 515*c2c66affSColin Finck { 516*c2c66affSColin Finck /* Only move the colors we need to */ 517*c2c66affSColin Finck if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 518*c2c66affSColin Finck { 519*c2c66affSColin Finck png_color tmp_color; 520*c2c66affSColin Finck 521*c2c66affSColin Finck do 522*c2c66affSColin Finck j--; 523*c2c66affSColin Finck while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 524*c2c66affSColin Finck 525*c2c66affSColin Finck tmp_color = palette[j]; 526*c2c66affSColin Finck palette[j] = palette[i]; 527*c2c66affSColin Finck palette[i] = tmp_color; 528*c2c66affSColin Finck /* Indicate where the color went */ 529*c2c66affSColin Finck png_ptr->quantize_index[j] = (png_byte)i; 530*c2c66affSColin Finck png_ptr->quantize_index[i] = (png_byte)j; 531*c2c66affSColin Finck } 532*c2c66affSColin Finck } 533*c2c66affSColin Finck 534*c2c66affSColin Finck /* Find closest color for those colors we are not using */ 535*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 536*c2c66affSColin Finck { 537*c2c66affSColin Finck if ((int)png_ptr->quantize_index[i] >= maximum_colors) 538*c2c66affSColin Finck { 539*c2c66affSColin Finck int min_d, k, min_k, d_index; 540*c2c66affSColin Finck 541*c2c66affSColin Finck /* Find the closest color to one we threw out */ 542*c2c66affSColin Finck d_index = png_ptr->quantize_index[i]; 543*c2c66affSColin Finck min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 544*c2c66affSColin Finck for (k = 1, min_k = 0; k < maximum_colors; k++) 545*c2c66affSColin Finck { 546*c2c66affSColin Finck int d; 547*c2c66affSColin Finck 548*c2c66affSColin Finck d = PNG_COLOR_DIST(palette[d_index], palette[k]); 549*c2c66affSColin Finck 550*c2c66affSColin Finck if (d < min_d) 551*c2c66affSColin Finck { 552*c2c66affSColin Finck min_d = d; 553*c2c66affSColin Finck min_k = k; 554*c2c66affSColin Finck } 555*c2c66affSColin Finck } 556*c2c66affSColin Finck /* Point to closest color */ 557*c2c66affSColin Finck png_ptr->quantize_index[i] = (png_byte)min_k; 558*c2c66affSColin Finck } 559*c2c66affSColin Finck } 560*c2c66affSColin Finck } 561*c2c66affSColin Finck png_free(png_ptr, png_ptr->quantize_sort); 562*c2c66affSColin Finck png_ptr->quantize_sort = NULL; 563*c2c66affSColin Finck } 564*c2c66affSColin Finck else 565*c2c66affSColin Finck { 566*c2c66affSColin Finck /* This is much harder to do simply (and quickly). Perhaps 567*c2c66affSColin Finck * we need to go through a median cut routine, but those 568*c2c66affSColin Finck * don't always behave themselves with only a few colors 569*c2c66affSColin Finck * as input. So we will just find the closest two colors, 570*c2c66affSColin Finck * and throw out one of them (chosen somewhat randomly). 571*c2c66affSColin Finck * [We don't understand this at all, so if someone wants to 572*c2c66affSColin Finck * work on improving it, be our guest - AED, GRP] 573*c2c66affSColin Finck */ 574*c2c66affSColin Finck int i; 575*c2c66affSColin Finck int max_d; 576*c2c66affSColin Finck int num_new_palette; 577*c2c66affSColin Finck png_dsortp t; 578*c2c66affSColin Finck png_dsortpp hash; 579*c2c66affSColin Finck 580*c2c66affSColin Finck t = NULL; 581*c2c66affSColin Finck 582*c2c66affSColin Finck /* Initialize palette index arrays */ 583*c2c66affSColin Finck png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 584*c2c66affSColin Finck (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); 585*c2c66affSColin Finck png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 586*c2c66affSColin Finck (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); 587*c2c66affSColin Finck 588*c2c66affSColin Finck /* Initialize the sort array */ 589*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 590*c2c66affSColin Finck { 591*c2c66affSColin Finck png_ptr->index_to_palette[i] = (png_byte)i; 592*c2c66affSColin Finck png_ptr->palette_to_index[i] = (png_byte)i; 593*c2c66affSColin Finck } 594*c2c66affSColin Finck 595*c2c66affSColin Finck hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * 596*c2c66affSColin Finck (sizeof (png_dsortp)))); 597*c2c66affSColin Finck 598*c2c66affSColin Finck num_new_palette = num_palette; 599*c2c66affSColin Finck 600*c2c66affSColin Finck /* Initial wild guess at how far apart the farthest pixel 601*c2c66affSColin Finck * pair we will be eliminating will be. Larger 602*c2c66affSColin Finck * numbers mean more areas will be allocated, Smaller 603*c2c66affSColin Finck * numbers run the risk of not saving enough data, and 604*c2c66affSColin Finck * having to do this all over again. 605*c2c66affSColin Finck * 606*c2c66affSColin Finck * I have not done extensive checking on this number. 607*c2c66affSColin Finck */ 608*c2c66affSColin Finck max_d = 96; 609*c2c66affSColin Finck 610*c2c66affSColin Finck while (num_new_palette > maximum_colors) 611*c2c66affSColin Finck { 612*c2c66affSColin Finck for (i = 0; i < num_new_palette - 1; i++) 613*c2c66affSColin Finck { 614*c2c66affSColin Finck int j; 615*c2c66affSColin Finck 616*c2c66affSColin Finck for (j = i + 1; j < num_new_palette; j++) 617*c2c66affSColin Finck { 618*c2c66affSColin Finck int d; 619*c2c66affSColin Finck 620*c2c66affSColin Finck d = PNG_COLOR_DIST(palette[i], palette[j]); 621*c2c66affSColin Finck 622*c2c66affSColin Finck if (d <= max_d) 623*c2c66affSColin Finck { 624*c2c66affSColin Finck 625*c2c66affSColin Finck t = (png_dsortp)png_malloc_warn(png_ptr, 626*c2c66affSColin Finck (png_uint_32)(sizeof (png_dsort))); 627*c2c66affSColin Finck 628*c2c66affSColin Finck if (t == NULL) 629*c2c66affSColin Finck break; 630*c2c66affSColin Finck 631*c2c66affSColin Finck t->next = hash[d]; 632*c2c66affSColin Finck t->left = (png_byte)i; 633*c2c66affSColin Finck t->right = (png_byte)j; 634*c2c66affSColin Finck hash[d] = t; 635*c2c66affSColin Finck } 636*c2c66affSColin Finck } 637*c2c66affSColin Finck if (t == NULL) 638*c2c66affSColin Finck break; 639*c2c66affSColin Finck } 640*c2c66affSColin Finck 641*c2c66affSColin Finck if (t != NULL) 642*c2c66affSColin Finck for (i = 0; i <= max_d; i++) 643*c2c66affSColin Finck { 644*c2c66affSColin Finck if (hash[i] != NULL) 645*c2c66affSColin Finck { 646*c2c66affSColin Finck png_dsortp p; 647*c2c66affSColin Finck 648*c2c66affSColin Finck for (p = hash[i]; p; p = p->next) 649*c2c66affSColin Finck { 650*c2c66affSColin Finck if ((int)png_ptr->index_to_palette[p->left] 651*c2c66affSColin Finck < num_new_palette && 652*c2c66affSColin Finck (int)png_ptr->index_to_palette[p->right] 653*c2c66affSColin Finck < num_new_palette) 654*c2c66affSColin Finck { 655*c2c66affSColin Finck int j, next_j; 656*c2c66affSColin Finck 657*c2c66affSColin Finck if (num_new_palette & 0x01) 658*c2c66affSColin Finck { 659*c2c66affSColin Finck j = p->left; 660*c2c66affSColin Finck next_j = p->right; 661*c2c66affSColin Finck } 662*c2c66affSColin Finck else 663*c2c66affSColin Finck { 664*c2c66affSColin Finck j = p->right; 665*c2c66affSColin Finck next_j = p->left; 666*c2c66affSColin Finck } 667*c2c66affSColin Finck 668*c2c66affSColin Finck num_new_palette--; 669*c2c66affSColin Finck palette[png_ptr->index_to_palette[j]] 670*c2c66affSColin Finck = palette[num_new_palette]; 671*c2c66affSColin Finck if (full_quantize == 0) 672*c2c66affSColin Finck { 673*c2c66affSColin Finck int k; 674*c2c66affSColin Finck 675*c2c66affSColin Finck for (k = 0; k < num_palette; k++) 676*c2c66affSColin Finck { 677*c2c66affSColin Finck if (png_ptr->quantize_index[k] == 678*c2c66affSColin Finck png_ptr->index_to_palette[j]) 679*c2c66affSColin Finck png_ptr->quantize_index[k] = 680*c2c66affSColin Finck png_ptr->index_to_palette[next_j]; 681*c2c66affSColin Finck 682*c2c66affSColin Finck if ((int)png_ptr->quantize_index[k] == 683*c2c66affSColin Finck num_new_palette) 684*c2c66affSColin Finck png_ptr->quantize_index[k] = 685*c2c66affSColin Finck png_ptr->index_to_palette[j]; 686*c2c66affSColin Finck } 687*c2c66affSColin Finck } 688*c2c66affSColin Finck 689*c2c66affSColin Finck png_ptr->index_to_palette[png_ptr->palette_to_index 690*c2c66affSColin Finck [num_new_palette]] = png_ptr->index_to_palette[j]; 691*c2c66affSColin Finck 692*c2c66affSColin Finck png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 693*c2c66affSColin Finck = png_ptr->palette_to_index[num_new_palette]; 694*c2c66affSColin Finck 695*c2c66affSColin Finck png_ptr->index_to_palette[j] = 696*c2c66affSColin Finck (png_byte)num_new_palette; 697*c2c66affSColin Finck 698*c2c66affSColin Finck png_ptr->palette_to_index[num_new_palette] = 699*c2c66affSColin Finck (png_byte)j; 700*c2c66affSColin Finck } 701*c2c66affSColin Finck if (num_new_palette <= maximum_colors) 702*c2c66affSColin Finck break; 703*c2c66affSColin Finck } 704*c2c66affSColin Finck if (num_new_palette <= maximum_colors) 705*c2c66affSColin Finck break; 706*c2c66affSColin Finck } 707*c2c66affSColin Finck } 708*c2c66affSColin Finck 709*c2c66affSColin Finck for (i = 0; i < 769; i++) 710*c2c66affSColin Finck { 711*c2c66affSColin Finck if (hash[i] != NULL) 712*c2c66affSColin Finck { 713*c2c66affSColin Finck png_dsortp p = hash[i]; 714*c2c66affSColin Finck while (p) 715*c2c66affSColin Finck { 716*c2c66affSColin Finck t = p->next; 717*c2c66affSColin Finck png_free(png_ptr, p); 718*c2c66affSColin Finck p = t; 719*c2c66affSColin Finck } 720*c2c66affSColin Finck } 721*c2c66affSColin Finck hash[i] = 0; 722*c2c66affSColin Finck } 723*c2c66affSColin Finck max_d += 96; 724*c2c66affSColin Finck } 725*c2c66affSColin Finck png_free(png_ptr, hash); 726*c2c66affSColin Finck png_free(png_ptr, png_ptr->palette_to_index); 727*c2c66affSColin Finck png_free(png_ptr, png_ptr->index_to_palette); 728*c2c66affSColin Finck png_ptr->palette_to_index = NULL; 729*c2c66affSColin Finck png_ptr->index_to_palette = NULL; 730*c2c66affSColin Finck } 731*c2c66affSColin Finck num_palette = maximum_colors; 732*c2c66affSColin Finck } 733*c2c66affSColin Finck if (png_ptr->palette == NULL) 734*c2c66affSColin Finck { 735*c2c66affSColin Finck png_ptr->palette = palette; 736*c2c66affSColin Finck } 737*c2c66affSColin Finck png_ptr->num_palette = (png_uint_16)num_palette; 738*c2c66affSColin Finck 739*c2c66affSColin Finck if (full_quantize != 0) 740*c2c66affSColin Finck { 741*c2c66affSColin Finck int i; 742*c2c66affSColin Finck png_bytep distance; 743*c2c66affSColin Finck int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + 744*c2c66affSColin Finck PNG_QUANTIZE_BLUE_BITS; 745*c2c66affSColin Finck int num_red = (1 << PNG_QUANTIZE_RED_BITS); 746*c2c66affSColin Finck int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); 747*c2c66affSColin Finck int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); 748*c2c66affSColin Finck png_size_t num_entries = ((png_size_t)1 << total_bits); 749*c2c66affSColin Finck 750*c2c66affSColin Finck png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, 751*c2c66affSColin Finck (png_uint_32)(num_entries * (sizeof (png_byte)))); 752*c2c66affSColin Finck 753*c2c66affSColin Finck distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 754*c2c66affSColin Finck (sizeof (png_byte)))); 755*c2c66affSColin Finck 756*c2c66affSColin Finck memset(distance, 0xff, num_entries * (sizeof (png_byte))); 757*c2c66affSColin Finck 758*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 759*c2c66affSColin Finck { 760*c2c66affSColin Finck int ir, ig, ib; 761*c2c66affSColin Finck int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); 762*c2c66affSColin Finck int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); 763*c2c66affSColin Finck int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); 764*c2c66affSColin Finck 765*c2c66affSColin Finck for (ir = 0; ir < num_red; ir++) 766*c2c66affSColin Finck { 767*c2c66affSColin Finck /* int dr = abs(ir - r); */ 768*c2c66affSColin Finck int dr = ((ir > r) ? ir - r : r - ir); 769*c2c66affSColin Finck int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + 770*c2c66affSColin Finck PNG_QUANTIZE_GREEN_BITS)); 771*c2c66affSColin Finck 772*c2c66affSColin Finck for (ig = 0; ig < num_green; ig++) 773*c2c66affSColin Finck { 774*c2c66affSColin Finck /* int dg = abs(ig - g); */ 775*c2c66affSColin Finck int dg = ((ig > g) ? ig - g : g - ig); 776*c2c66affSColin Finck int dt = dr + dg; 777*c2c66affSColin Finck int dm = ((dr > dg) ? dr : dg); 778*c2c66affSColin Finck int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); 779*c2c66affSColin Finck 780*c2c66affSColin Finck for (ib = 0; ib < num_blue; ib++) 781*c2c66affSColin Finck { 782*c2c66affSColin Finck int d_index = index_g | ib; 783*c2c66affSColin Finck /* int db = abs(ib - b); */ 784*c2c66affSColin Finck int db = ((ib > b) ? ib - b : b - ib); 785*c2c66affSColin Finck int dmax = ((dm > db) ? dm : db); 786*c2c66affSColin Finck int d = dmax + dt + db; 787*c2c66affSColin Finck 788*c2c66affSColin Finck if (d < (int)distance[d_index]) 789*c2c66affSColin Finck { 790*c2c66affSColin Finck distance[d_index] = (png_byte)d; 791*c2c66affSColin Finck png_ptr->palette_lookup[d_index] = (png_byte)i; 792*c2c66affSColin Finck } 793*c2c66affSColin Finck } 794*c2c66affSColin Finck } 795*c2c66affSColin Finck } 796*c2c66affSColin Finck } 797*c2c66affSColin Finck 798*c2c66affSColin Finck png_free(png_ptr, distance); 799*c2c66affSColin Finck } 800*c2c66affSColin Finck } 801*c2c66affSColin Finck #endif /* READ_QUANTIZE */ 802*c2c66affSColin Finck 803*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 804*c2c66affSColin Finck void PNGFAPI 805*c2c66affSColin Finck png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, 806*c2c66affSColin Finck png_fixed_point file_gamma) 807*c2c66affSColin Finck { 808*c2c66affSColin Finck png_debug(1, "in png_set_gamma_fixed"); 809*c2c66affSColin Finck 810*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 811*c2c66affSColin Finck return; 812*c2c66affSColin Finck 813*c2c66affSColin Finck /* New in libpng-1.5.4 - reserve particular negative values as flags. */ 814*c2c66affSColin Finck scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); 815*c2c66affSColin Finck file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); 816*c2c66affSColin Finck 817*c2c66affSColin Finck /* Checking the gamma values for being >0 was added in 1.5.4 along with the 818*c2c66affSColin Finck * premultiplied alpha support; this actually hides an undocumented feature 819*c2c66affSColin Finck * of the previous implementation which allowed gamma processing to be 820*c2c66affSColin Finck * disabled in background handling. There is no evidence (so far) that this 821*c2c66affSColin Finck * was being used; however, png_set_background itself accepted and must still 822*c2c66affSColin Finck * accept '0' for the gamma value it takes, because it isn't always used. 823*c2c66affSColin Finck * 824*c2c66affSColin Finck * Since this is an API change (albeit a very minor one that removes an 825*c2c66affSColin Finck * undocumented API feature) the following checks were only enabled in 826*c2c66affSColin Finck * libpng-1.6.0. 827*c2c66affSColin Finck */ 828*c2c66affSColin Finck if (file_gamma <= 0) 829*c2c66affSColin Finck png_error(png_ptr, "invalid file gamma in png_set_gamma"); 830*c2c66affSColin Finck 831*c2c66affSColin Finck if (scrn_gamma <= 0) 832*c2c66affSColin Finck png_error(png_ptr, "invalid screen gamma in png_set_gamma"); 833*c2c66affSColin Finck 834*c2c66affSColin Finck /* Set the gamma values unconditionally - this overrides the value in the PNG 835*c2c66affSColin Finck * file if a gAMA chunk was present. png_set_alpha_mode provides a 836*c2c66affSColin Finck * different, easier, way to default the file gamma. 837*c2c66affSColin Finck */ 838*c2c66affSColin Finck png_ptr->colorspace.gamma = file_gamma; 839*c2c66affSColin Finck png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 840*c2c66affSColin Finck png_ptr->screen_gamma = scrn_gamma; 841*c2c66affSColin Finck } 842*c2c66affSColin Finck 843*c2c66affSColin Finck # ifdef PNG_FLOATING_POINT_SUPPORTED 844*c2c66affSColin Finck void PNGAPI 845*c2c66affSColin Finck png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) 846*c2c66affSColin Finck { 847*c2c66affSColin Finck png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), 848*c2c66affSColin Finck convert_gamma_value(png_ptr, file_gamma)); 849*c2c66affSColin Finck } 850*c2c66affSColin Finck # endif /* FLOATING_POINT */ 851*c2c66affSColin Finck #endif /* READ_GAMMA */ 852*c2c66affSColin Finck 853*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_SUPPORTED 854*c2c66affSColin Finck /* Expand paletted images to RGB, expand grayscale images of 855*c2c66affSColin Finck * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 856*c2c66affSColin Finck * to alpha channels. 857*c2c66affSColin Finck */ 858*c2c66affSColin Finck void PNGAPI 859*c2c66affSColin Finck png_set_expand(png_structrp png_ptr) 860*c2c66affSColin Finck { 861*c2c66affSColin Finck png_debug(1, "in png_set_expand"); 862*c2c66affSColin Finck 863*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 864*c2c66affSColin Finck return; 865*c2c66affSColin Finck 866*c2c66affSColin Finck png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 867*c2c66affSColin Finck } 868*c2c66affSColin Finck 869*c2c66affSColin Finck /* GRR 19990627: the following three functions currently are identical 870*c2c66affSColin Finck * to png_set_expand(). However, it is entirely reasonable that someone 871*c2c66affSColin Finck * might wish to expand an indexed image to RGB but *not* expand a single, 872*c2c66affSColin Finck * fully transparent palette entry to a full alpha channel--perhaps instead 873*c2c66affSColin Finck * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 874*c2c66affSColin Finck * the transparent color with a particular RGB value, or drop tRNS entirely. 875*c2c66affSColin Finck * IOW, a future version of the library may make the transformations flag 876*c2c66affSColin Finck * a bit more fine-grained, with separate bits for each of these three 877*c2c66affSColin Finck * functions. 878*c2c66affSColin Finck * 879*c2c66affSColin Finck * More to the point, these functions make it obvious what libpng will be 880*c2c66affSColin Finck * doing, whereas "expand" can (and does) mean any number of things. 881*c2c66affSColin Finck * 882*c2c66affSColin Finck * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified 883*c2c66affSColin Finck * to expand only the sample depth but not to expand the tRNS to alpha 884*c2c66affSColin Finck * and its name was changed to png_set_expand_gray_1_2_4_to_8(). 885*c2c66affSColin Finck */ 886*c2c66affSColin Finck 887*c2c66affSColin Finck /* Expand paletted images to RGB. */ 888*c2c66affSColin Finck void PNGAPI 889*c2c66affSColin Finck png_set_palette_to_rgb(png_structrp png_ptr) 890*c2c66affSColin Finck { 891*c2c66affSColin Finck png_debug(1, "in png_set_palette_to_rgb"); 892*c2c66affSColin Finck 893*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 894*c2c66affSColin Finck return; 895*c2c66affSColin Finck 896*c2c66affSColin Finck png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 897*c2c66affSColin Finck } 898*c2c66affSColin Finck 899*c2c66affSColin Finck /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 900*c2c66affSColin Finck void PNGAPI 901*c2c66affSColin Finck png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) 902*c2c66affSColin Finck { 903*c2c66affSColin Finck png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); 904*c2c66affSColin Finck 905*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 906*c2c66affSColin Finck return; 907*c2c66affSColin Finck 908*c2c66affSColin Finck png_ptr->transformations |= PNG_EXPAND; 909*c2c66affSColin Finck } 910*c2c66affSColin Finck 911*c2c66affSColin Finck /* Expand tRNS chunks to alpha channels. */ 912*c2c66affSColin Finck void PNGAPI 913*c2c66affSColin Finck png_set_tRNS_to_alpha(png_structrp png_ptr) 914*c2c66affSColin Finck { 915*c2c66affSColin Finck png_debug(1, "in png_set_tRNS_to_alpha"); 916*c2c66affSColin Finck 917*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 918*c2c66affSColin Finck return; 919*c2c66affSColin Finck 920*c2c66affSColin Finck png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 921*c2c66affSColin Finck } 922*c2c66affSColin Finck #endif /* READ_EXPAND */ 923*c2c66affSColin Finck 924*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_16_SUPPORTED 925*c2c66affSColin Finck /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise 926*c2c66affSColin Finck * it may not work correctly.) 927*c2c66affSColin Finck */ 928*c2c66affSColin Finck void PNGAPI 929*c2c66affSColin Finck png_set_expand_16(png_structrp png_ptr) 930*c2c66affSColin Finck { 931*c2c66affSColin Finck png_debug(1, "in png_set_expand_16"); 932*c2c66affSColin Finck 933*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 934*c2c66affSColin Finck return; 935*c2c66affSColin Finck 936*c2c66affSColin Finck png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); 937*c2c66affSColin Finck } 938*c2c66affSColin Finck #endif 939*c2c66affSColin Finck 940*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 941*c2c66affSColin Finck void PNGAPI 942*c2c66affSColin Finck png_set_gray_to_rgb(png_structrp png_ptr) 943*c2c66affSColin Finck { 944*c2c66affSColin Finck png_debug(1, "in png_set_gray_to_rgb"); 945*c2c66affSColin Finck 946*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 0) == 0) 947*c2c66affSColin Finck return; 948*c2c66affSColin Finck 949*c2c66affSColin Finck /* Because rgb must be 8 bits or more: */ 950*c2c66affSColin Finck png_set_expand_gray_1_2_4_to_8(png_ptr); 951*c2c66affSColin Finck png_ptr->transformations |= PNG_GRAY_TO_RGB; 952*c2c66affSColin Finck } 953*c2c66affSColin Finck #endif 954*c2c66affSColin Finck 955*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 956*c2c66affSColin Finck void PNGFAPI 957*c2c66affSColin Finck png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, 958*c2c66affSColin Finck png_fixed_point red, png_fixed_point green) 959*c2c66affSColin Finck { 960*c2c66affSColin Finck png_debug(1, "in png_set_rgb_to_gray"); 961*c2c66affSColin Finck 962*c2c66affSColin Finck /* Need the IHDR here because of the check on color_type below. */ 963*c2c66affSColin Finck /* TODO: fix this */ 964*c2c66affSColin Finck if (png_rtran_ok(png_ptr, 1) == 0) 965*c2c66affSColin Finck return; 966*c2c66affSColin Finck 967*c2c66affSColin Finck switch (error_action) 968*c2c66affSColin Finck { 969*c2c66affSColin Finck case PNG_ERROR_ACTION_NONE: 970*c2c66affSColin Finck png_ptr->transformations |= PNG_RGB_TO_GRAY; 971*c2c66affSColin Finck break; 972*c2c66affSColin Finck 973*c2c66affSColin Finck case PNG_ERROR_ACTION_WARN: 974*c2c66affSColin Finck png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 975*c2c66affSColin Finck break; 976*c2c66affSColin Finck 977*c2c66affSColin Finck case PNG_ERROR_ACTION_ERROR: 978*c2c66affSColin Finck png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 979*c2c66affSColin Finck break; 980*c2c66affSColin Finck 981*c2c66affSColin Finck default: 982*c2c66affSColin Finck png_error(png_ptr, "invalid error action to rgb_to_gray"); 983*c2c66affSColin Finck } 984*c2c66affSColin Finck 985*c2c66affSColin Finck if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 986*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_SUPPORTED 987*c2c66affSColin Finck png_ptr->transformations |= PNG_EXPAND; 988*c2c66affSColin Finck #else 989*c2c66affSColin Finck { 990*c2c66affSColin Finck /* Make this an error in 1.6 because otherwise the application may assume 991*c2c66affSColin Finck * that it just worked and get a memory overwrite. 992*c2c66affSColin Finck */ 993*c2c66affSColin Finck png_error(png_ptr, 994*c2c66affSColin Finck "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); 995*c2c66affSColin Finck 996*c2c66affSColin Finck /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ 997*c2c66affSColin Finck } 998*c2c66affSColin Finck #endif 999*c2c66affSColin Finck { 1000*c2c66affSColin Finck if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) 1001*c2c66affSColin Finck { 1002*c2c66affSColin Finck png_uint_16 red_int, green_int; 1003*c2c66affSColin Finck 1004*c2c66affSColin Finck /* NOTE: this calculation does not round, but this behavior is retained 1005*c2c66affSColin Finck * for consistency; the inaccuracy is very small. The code here always 1006*c2c66affSColin Finck * overwrites the coefficients, regardless of whether they have been 1007*c2c66affSColin Finck * defaulted or set already. 1008*c2c66affSColin Finck */ 1009*c2c66affSColin Finck red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); 1010*c2c66affSColin Finck green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); 1011*c2c66affSColin Finck 1012*c2c66affSColin Finck png_ptr->rgb_to_gray_red_coeff = red_int; 1013*c2c66affSColin Finck png_ptr->rgb_to_gray_green_coeff = green_int; 1014*c2c66affSColin Finck png_ptr->rgb_to_gray_coefficients_set = 1; 1015*c2c66affSColin Finck } 1016*c2c66affSColin Finck 1017*c2c66affSColin Finck else 1018*c2c66affSColin Finck { 1019*c2c66affSColin Finck if (red >= 0 && green >= 0) 1020*c2c66affSColin Finck png_app_warning(png_ptr, 1021*c2c66affSColin Finck "ignoring out of range rgb_to_gray coefficients"); 1022*c2c66affSColin Finck 1023*c2c66affSColin Finck /* Use the defaults, from the cHRM chunk if set, else the historical 1024*c2c66affSColin Finck * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See 1025*c2c66affSColin Finck * png_do_rgb_to_gray for more discussion of the values. In this case 1026*c2c66affSColin Finck * the coefficients are not marked as 'set' and are not overwritten if 1027*c2c66affSColin Finck * something has already provided a default. 1028*c2c66affSColin Finck */ 1029*c2c66affSColin Finck if (png_ptr->rgb_to_gray_red_coeff == 0 && 1030*c2c66affSColin Finck png_ptr->rgb_to_gray_green_coeff == 0) 1031*c2c66affSColin Finck { 1032*c2c66affSColin Finck png_ptr->rgb_to_gray_red_coeff = 6968; 1033*c2c66affSColin Finck png_ptr->rgb_to_gray_green_coeff = 23434; 1034*c2c66affSColin Finck /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ 1035*c2c66affSColin Finck } 1036*c2c66affSColin Finck } 1037*c2c66affSColin Finck } 1038*c2c66affSColin Finck } 1039*c2c66affSColin Finck 1040*c2c66affSColin Finck #ifdef PNG_FLOATING_POINT_SUPPORTED 1041*c2c66affSColin Finck /* Convert a RGB image to a grayscale of the same width. This allows us, 1042*c2c66affSColin Finck * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 1043*c2c66affSColin Finck */ 1044*c2c66affSColin Finck 1045*c2c66affSColin Finck void PNGAPI 1046*c2c66affSColin Finck png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, 1047*c2c66affSColin Finck double green) 1048*c2c66affSColin Finck { 1049*c2c66affSColin Finck png_set_rgb_to_gray_fixed(png_ptr, error_action, 1050*c2c66affSColin Finck png_fixed(png_ptr, red, "rgb to gray red coefficient"), 1051*c2c66affSColin Finck png_fixed(png_ptr, green, "rgb to gray green coefficient")); 1052*c2c66affSColin Finck } 1053*c2c66affSColin Finck #endif /* FLOATING POINT */ 1054*c2c66affSColin Finck 1055*c2c66affSColin Finck #endif /* RGB_TO_GRAY */ 1056*c2c66affSColin Finck 1057*c2c66affSColin Finck #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 1058*c2c66affSColin Finck defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 1059*c2c66affSColin Finck void PNGAPI 1060*c2c66affSColin Finck png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr 1061*c2c66affSColin Finck read_user_transform_fn) 1062*c2c66affSColin Finck { 1063*c2c66affSColin Finck png_debug(1, "in png_set_read_user_transform_fn"); 1064*c2c66affSColin Finck 1065*c2c66affSColin Finck #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1066*c2c66affSColin Finck png_ptr->transformations |= PNG_USER_TRANSFORM; 1067*c2c66affSColin Finck png_ptr->read_user_transform_fn = read_user_transform_fn; 1068*c2c66affSColin Finck #endif 1069*c2c66affSColin Finck } 1070*c2c66affSColin Finck #endif 1071*c2c66affSColin Finck 1072*c2c66affSColin Finck #ifdef PNG_READ_TRANSFORMS_SUPPORTED 1073*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 1074*c2c66affSColin Finck /* In the case of gamma transformations only do transformations on images where 1075*c2c66affSColin Finck * the [file] gamma and screen_gamma are not close reciprocals, otherwise it 1076*c2c66affSColin Finck * slows things down slightly, and also needlessly introduces small errors. 1077*c2c66affSColin Finck */ 1078*c2c66affSColin Finck static int /* PRIVATE */ 1079*c2c66affSColin Finck png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) 1080*c2c66affSColin Finck { 1081*c2c66affSColin Finck /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma 1082*c2c66affSColin Finck * correction as a difference of the overall transform from 1.0 1083*c2c66affSColin Finck * 1084*c2c66affSColin Finck * We want to compare the threshold with s*f - 1, if we get 1085*c2c66affSColin Finck * overflow here it is because of wacky gamma values so we 1086*c2c66affSColin Finck * turn on processing anyway. 1087*c2c66affSColin Finck */ 1088*c2c66affSColin Finck png_fixed_point gtest; 1089*c2c66affSColin Finck return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || 1090*c2c66affSColin Finck png_gamma_significant(gtest); 1091*c2c66affSColin Finck } 1092*c2c66affSColin Finck #endif 1093*c2c66affSColin Finck 1094*c2c66affSColin Finck /* Initialize everything needed for the read. This includes modifying 1095*c2c66affSColin Finck * the palette. 1096*c2c66affSColin Finck */ 1097*c2c66affSColin Finck 1098*c2c66affSColin Finck /* For the moment 'png_init_palette_transformations' and 1099*c2c66affSColin Finck * 'png_init_rgb_transformations' only do some flag canceling optimizations. 1100*c2c66affSColin Finck * The intent is that these two routines should have palette or rgb operations 1101*c2c66affSColin Finck * extracted from 'png_init_read_transformations'. 1102*c2c66affSColin Finck */ 1103*c2c66affSColin Finck static void /* PRIVATE */ 1104*c2c66affSColin Finck png_init_palette_transformations(png_structrp png_ptr) 1105*c2c66affSColin Finck { 1106*c2c66affSColin Finck /* Called to handle the (input) palette case. In png_do_read_transformations 1107*c2c66affSColin Finck * the first step is to expand the palette if requested, so this code must 1108*c2c66affSColin Finck * take care to only make changes that are invariant with respect to the 1109*c2c66affSColin Finck * palette expansion, or only do them if there is no expansion. 1110*c2c66affSColin Finck * 1111*c2c66affSColin Finck * STRIP_ALPHA has already been handled in the caller (by setting num_trans 1112*c2c66affSColin Finck * to 0.) 1113*c2c66affSColin Finck */ 1114*c2c66affSColin Finck int input_has_alpha = 0; 1115*c2c66affSColin Finck int input_has_transparency = 0; 1116*c2c66affSColin Finck 1117*c2c66affSColin Finck if (png_ptr->num_trans > 0) 1118*c2c66affSColin Finck { 1119*c2c66affSColin Finck int i; 1120*c2c66affSColin Finck 1121*c2c66affSColin Finck /* Ignore if all the entries are opaque (unlikely!) */ 1122*c2c66affSColin Finck for (i=0; i<png_ptr->num_trans; ++i) 1123*c2c66affSColin Finck { 1124*c2c66affSColin Finck if (png_ptr->trans_alpha[i] == 255) 1125*c2c66affSColin Finck continue; 1126*c2c66affSColin Finck else if (png_ptr->trans_alpha[i] == 0) 1127*c2c66affSColin Finck input_has_transparency = 1; 1128*c2c66affSColin Finck else 1129*c2c66affSColin Finck { 1130*c2c66affSColin Finck input_has_transparency = 1; 1131*c2c66affSColin Finck input_has_alpha = 1; 1132*c2c66affSColin Finck break; 1133*c2c66affSColin Finck } 1134*c2c66affSColin Finck } 1135*c2c66affSColin Finck } 1136*c2c66affSColin Finck 1137*c2c66affSColin Finck /* If no alpha we can optimize. */ 1138*c2c66affSColin Finck if (input_has_alpha == 0) 1139*c2c66affSColin Finck { 1140*c2c66affSColin Finck /* Any alpha means background and associative alpha processing is 1141*c2c66affSColin Finck * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA 1142*c2c66affSColin Finck * and ENCODE_ALPHA are irrelevant. 1143*c2c66affSColin Finck */ 1144*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1145*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1146*c2c66affSColin Finck 1147*c2c66affSColin Finck if (input_has_transparency == 0) 1148*c2c66affSColin Finck png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 1149*c2c66affSColin Finck } 1150*c2c66affSColin Finck 1151*c2c66affSColin Finck #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1152*c2c66affSColin Finck /* png_set_background handling - deals with the complexity of whether the 1153*c2c66affSColin Finck * background color is in the file format or the screen format in the case 1154*c2c66affSColin Finck * where an 'expand' will happen. 1155*c2c66affSColin Finck */ 1156*c2c66affSColin Finck 1157*c2c66affSColin Finck /* The following code cannot be entered in the alpha pre-multiplication case 1158*c2c66affSColin Finck * because PNG_BACKGROUND_EXPAND is cancelled below. 1159*c2c66affSColin Finck */ 1160*c2c66affSColin Finck if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 && 1161*c2c66affSColin Finck (png_ptr->transformations & PNG_EXPAND) != 0) 1162*c2c66affSColin Finck { 1163*c2c66affSColin Finck { 1164*c2c66affSColin Finck png_ptr->background.red = 1165*c2c66affSColin Finck png_ptr->palette[png_ptr->background.index].red; 1166*c2c66affSColin Finck png_ptr->background.green = 1167*c2c66affSColin Finck png_ptr->palette[png_ptr->background.index].green; 1168*c2c66affSColin Finck png_ptr->background.blue = 1169*c2c66affSColin Finck png_ptr->palette[png_ptr->background.index].blue; 1170*c2c66affSColin Finck 1171*c2c66affSColin Finck #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1172*c2c66affSColin Finck if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) 1173*c2c66affSColin Finck { 1174*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) 1175*c2c66affSColin Finck { 1176*c2c66affSColin Finck /* Invert the alpha channel (in tRNS) unless the pixels are 1177*c2c66affSColin Finck * going to be expanded, in which case leave it for later 1178*c2c66affSColin Finck */ 1179*c2c66affSColin Finck int i, istop = png_ptr->num_trans; 1180*c2c66affSColin Finck 1181*c2c66affSColin Finck for (i=0; i<istop; i++) 1182*c2c66affSColin Finck png_ptr->trans_alpha[i] = (png_byte)(255 - 1183*c2c66affSColin Finck png_ptr->trans_alpha[i]); 1184*c2c66affSColin Finck } 1185*c2c66affSColin Finck } 1186*c2c66affSColin Finck #endif /* READ_INVERT_ALPHA */ 1187*c2c66affSColin Finck } 1188*c2c66affSColin Finck } /* background expand and (therefore) no alpha association. */ 1189*c2c66affSColin Finck #endif /* READ_EXPAND && READ_BACKGROUND */ 1190*c2c66affSColin Finck } 1191*c2c66affSColin Finck 1192*c2c66affSColin Finck static void /* PRIVATE */ 1193*c2c66affSColin Finck png_init_rgb_transformations(png_structrp png_ptr) 1194*c2c66affSColin Finck { 1195*c2c66affSColin Finck /* Added to libpng-1.5.4: check the color type to determine whether there 1196*c2c66affSColin Finck * is any alpha or transparency in the image and simply cancel the 1197*c2c66affSColin Finck * background and alpha mode stuff if there isn't. 1198*c2c66affSColin Finck */ 1199*c2c66affSColin Finck int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; 1200*c2c66affSColin Finck int input_has_transparency = png_ptr->num_trans > 0; 1201*c2c66affSColin Finck 1202*c2c66affSColin Finck /* If no alpha we can optimize. */ 1203*c2c66affSColin Finck if (input_has_alpha == 0) 1204*c2c66affSColin Finck { 1205*c2c66affSColin Finck /* Any alpha means background and associative alpha processing is 1206*c2c66affSColin Finck * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA 1207*c2c66affSColin Finck * and ENCODE_ALPHA are irrelevant. 1208*c2c66affSColin Finck */ 1209*c2c66affSColin Finck # ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1210*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1211*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1212*c2c66affSColin Finck # endif 1213*c2c66affSColin Finck 1214*c2c66affSColin Finck if (input_has_transparency == 0) 1215*c2c66affSColin Finck png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 1216*c2c66affSColin Finck } 1217*c2c66affSColin Finck 1218*c2c66affSColin Finck #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1219*c2c66affSColin Finck /* png_set_background handling - deals with the complexity of whether the 1220*c2c66affSColin Finck * background color is in the file format or the screen format in the case 1221*c2c66affSColin Finck * where an 'expand' will happen. 1222*c2c66affSColin Finck */ 1223*c2c66affSColin Finck 1224*c2c66affSColin Finck /* The following code cannot be entered in the alpha pre-multiplication case 1225*c2c66affSColin Finck * because PNG_BACKGROUND_EXPAND is cancelled below. 1226*c2c66affSColin Finck */ 1227*c2c66affSColin Finck if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 && 1228*c2c66affSColin Finck (png_ptr->transformations & PNG_EXPAND) != 0 && 1229*c2c66affSColin Finck (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) 1230*c2c66affSColin Finck /* i.e., GRAY or GRAY_ALPHA */ 1231*c2c66affSColin Finck { 1232*c2c66affSColin Finck { 1233*c2c66affSColin Finck /* Expand background and tRNS chunks */ 1234*c2c66affSColin Finck int gray = png_ptr->background.gray; 1235*c2c66affSColin Finck int trans_gray = png_ptr->trans_color.gray; 1236*c2c66affSColin Finck 1237*c2c66affSColin Finck switch (png_ptr->bit_depth) 1238*c2c66affSColin Finck { 1239*c2c66affSColin Finck case 1: 1240*c2c66affSColin Finck gray *= 0xff; 1241*c2c66affSColin Finck trans_gray *= 0xff; 1242*c2c66affSColin Finck break; 1243*c2c66affSColin Finck 1244*c2c66affSColin Finck case 2: 1245*c2c66affSColin Finck gray *= 0x55; 1246*c2c66affSColin Finck trans_gray *= 0x55; 1247*c2c66affSColin Finck break; 1248*c2c66affSColin Finck 1249*c2c66affSColin Finck case 4: 1250*c2c66affSColin Finck gray *= 0x11; 1251*c2c66affSColin Finck trans_gray *= 0x11; 1252*c2c66affSColin Finck break; 1253*c2c66affSColin Finck 1254*c2c66affSColin Finck default: 1255*c2c66affSColin Finck 1256*c2c66affSColin Finck case 8: 1257*c2c66affSColin Finck /* FALLTHROUGH */ /* (Already 8 bits) */ 1258*c2c66affSColin Finck 1259*c2c66affSColin Finck case 16: 1260*c2c66affSColin Finck /* Already a full 16 bits */ 1261*c2c66affSColin Finck break; 1262*c2c66affSColin Finck } 1263*c2c66affSColin Finck 1264*c2c66affSColin Finck png_ptr->background.red = png_ptr->background.green = 1265*c2c66affSColin Finck png_ptr->background.blue = (png_uint_16)gray; 1266*c2c66affSColin Finck 1267*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) 1268*c2c66affSColin Finck { 1269*c2c66affSColin Finck png_ptr->trans_color.red = png_ptr->trans_color.green = 1270*c2c66affSColin Finck png_ptr->trans_color.blue = (png_uint_16)trans_gray; 1271*c2c66affSColin Finck } 1272*c2c66affSColin Finck } 1273*c2c66affSColin Finck } /* background expand and (therefore) no alpha association. */ 1274*c2c66affSColin Finck #endif /* READ_EXPAND && READ_BACKGROUND */ 1275*c2c66affSColin Finck } 1276*c2c66affSColin Finck 1277*c2c66affSColin Finck void /* PRIVATE */ 1278*c2c66affSColin Finck png_init_read_transformations(png_structrp png_ptr) 1279*c2c66affSColin Finck { 1280*c2c66affSColin Finck png_debug(1, "in png_init_read_transformations"); 1281*c2c66affSColin Finck 1282*c2c66affSColin Finck /* This internal function is called from png_read_start_row in pngrutil.c 1283*c2c66affSColin Finck * and it is called before the 'rowbytes' calculation is done, so the code 1284*c2c66affSColin Finck * in here can change or update the transformations flags. 1285*c2c66affSColin Finck * 1286*c2c66affSColin Finck * First do updates that do not depend on the details of the PNG image data 1287*c2c66affSColin Finck * being processed. 1288*c2c66affSColin Finck */ 1289*c2c66affSColin Finck 1290*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 1291*c2c66affSColin Finck /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds 1292*c2c66affSColin Finck * png_set_alpha_mode and this is another source for a default file gamma so 1293*c2c66affSColin Finck * the test needs to be performed later - here. In addition prior to 1.5.4 1294*c2c66affSColin Finck * the tests were repeated for the PALETTE color type here - this is no 1295*c2c66affSColin Finck * longer necessary (and doesn't seem to have been necessary before.) 1296*c2c66affSColin Finck */ 1297*c2c66affSColin Finck { 1298*c2c66affSColin Finck /* The following temporary indicates if overall gamma correction is 1299*c2c66affSColin Finck * required. 1300*c2c66affSColin Finck */ 1301*c2c66affSColin Finck int gamma_correction = 0; 1302*c2c66affSColin Finck 1303*c2c66affSColin Finck if (png_ptr->colorspace.gamma != 0) /* has been set */ 1304*c2c66affSColin Finck { 1305*c2c66affSColin Finck if (png_ptr->screen_gamma != 0) /* screen set too */ 1306*c2c66affSColin Finck gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, 1307*c2c66affSColin Finck png_ptr->screen_gamma); 1308*c2c66affSColin Finck 1309*c2c66affSColin Finck else 1310*c2c66affSColin Finck /* Assume the output matches the input; a long time default behavior 1311*c2c66affSColin Finck * of libpng, although the standard has nothing to say about this. 1312*c2c66affSColin Finck */ 1313*c2c66affSColin Finck png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); 1314*c2c66affSColin Finck } 1315*c2c66affSColin Finck 1316*c2c66affSColin Finck else if (png_ptr->screen_gamma != 0) 1317*c2c66affSColin Finck /* The converse - assume the file matches the screen, note that this 1318*c2c66affSColin Finck * perhaps undesireable default can (from 1.5.4) be changed by calling 1319*c2c66affSColin Finck * png_set_alpha_mode (even if the alpha handling mode isn't required 1320*c2c66affSColin Finck * or isn't changed from the default.) 1321*c2c66affSColin Finck */ 1322*c2c66affSColin Finck png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); 1323*c2c66affSColin Finck 1324*c2c66affSColin Finck else /* neither are set */ 1325*c2c66affSColin Finck /* Just in case the following prevents any processing - file and screen 1326*c2c66affSColin Finck * are both assumed to be linear and there is no way to introduce a 1327*c2c66affSColin Finck * third gamma value other than png_set_background with 'UNIQUE', and, 1328*c2c66affSColin Finck * prior to 1.5.4 1329*c2c66affSColin Finck */ 1330*c2c66affSColin Finck png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; 1331*c2c66affSColin Finck 1332*c2c66affSColin Finck /* We have a gamma value now. */ 1333*c2c66affSColin Finck png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 1334*c2c66affSColin Finck 1335*c2c66affSColin Finck /* Now turn the gamma transformation on or off as appropriate. Notice 1336*c2c66affSColin Finck * that PNG_GAMMA just refers to the file->screen correction. Alpha 1337*c2c66affSColin Finck * composition may independently cause gamma correction because it needs 1338*c2c66affSColin Finck * linear data (e.g. if the file has a gAMA chunk but the screen gamma 1339*c2c66affSColin Finck * hasn't been specified.) In any case this flag may get turned off in 1340*c2c66affSColin Finck * the code immediately below if the transform can be handled outside the 1341*c2c66affSColin Finck * row loop. 1342*c2c66affSColin Finck */ 1343*c2c66affSColin Finck if (gamma_correction != 0) 1344*c2c66affSColin Finck png_ptr->transformations |= PNG_GAMMA; 1345*c2c66affSColin Finck 1346*c2c66affSColin Finck else 1347*c2c66affSColin Finck png_ptr->transformations &= ~PNG_GAMMA; 1348*c2c66affSColin Finck } 1349*c2c66affSColin Finck #endif 1350*c2c66affSColin Finck 1351*c2c66affSColin Finck /* Certain transformations have the effect of preventing other 1352*c2c66affSColin Finck * transformations that happen afterward in png_do_read_transformations; 1353*c2c66affSColin Finck * resolve the interdependencies here. From the code of 1354*c2c66affSColin Finck * png_do_read_transformations the order is: 1355*c2c66affSColin Finck * 1356*c2c66affSColin Finck * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) 1357*c2c66affSColin Finck * 2) PNG_STRIP_ALPHA (if no compose) 1358*c2c66affSColin Finck * 3) PNG_RGB_TO_GRAY 1359*c2c66affSColin Finck * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY 1360*c2c66affSColin Finck * 5) PNG_COMPOSE 1361*c2c66affSColin Finck * 6) PNG_GAMMA 1362*c2c66affSColin Finck * 7) PNG_STRIP_ALPHA (if compose) 1363*c2c66affSColin Finck * 8) PNG_ENCODE_ALPHA 1364*c2c66affSColin Finck * 9) PNG_SCALE_16_TO_8 1365*c2c66affSColin Finck * 10) PNG_16_TO_8 1366*c2c66affSColin Finck * 11) PNG_QUANTIZE (converts to palette) 1367*c2c66affSColin Finck * 12) PNG_EXPAND_16 1368*c2c66affSColin Finck * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY 1369*c2c66affSColin Finck * 14) PNG_INVERT_MONO 1370*c2c66affSColin Finck * 15) PNG_INVERT_ALPHA 1371*c2c66affSColin Finck * 16) PNG_SHIFT 1372*c2c66affSColin Finck * 17) PNG_PACK 1373*c2c66affSColin Finck * 18) PNG_BGR 1374*c2c66affSColin Finck * 19) PNG_PACKSWAP 1375*c2c66affSColin Finck * 20) PNG_FILLER (includes PNG_ADD_ALPHA) 1376*c2c66affSColin Finck * 21) PNG_SWAP_ALPHA 1377*c2c66affSColin Finck * 22) PNG_SWAP_BYTES 1378*c2c66affSColin Finck * 23) PNG_USER_TRANSFORM [must be last] 1379*c2c66affSColin Finck */ 1380*c2c66affSColin Finck #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1381*c2c66affSColin Finck if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 && 1382*c2c66affSColin Finck (png_ptr->transformations & PNG_COMPOSE) == 0) 1383*c2c66affSColin Finck { 1384*c2c66affSColin Finck /* Stripping the alpha channel happens immediately after the 'expand' 1385*c2c66affSColin Finck * transformations, before all other transformation, so it cancels out 1386*c2c66affSColin Finck * the alpha handling. It has the side effect negating the effect of 1387*c2c66affSColin Finck * PNG_EXPAND_tRNS too: 1388*c2c66affSColin Finck */ 1389*c2c66affSColin Finck png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | 1390*c2c66affSColin Finck PNG_EXPAND_tRNS); 1391*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1392*c2c66affSColin Finck 1393*c2c66affSColin Finck /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen 1394*c2c66affSColin Finck * so transparency information would remain just so long as it wasn't 1395*c2c66affSColin Finck * expanded. This produces unexpected API changes if the set of things 1396*c2c66affSColin Finck * that do PNG_EXPAND_tRNS changes (perfectly possible given the 1397*c2c66affSColin Finck * documentation - which says ask for what you want, accept what you 1398*c2c66affSColin Finck * get.) This makes the behavior consistent from 1.5.4: 1399*c2c66affSColin Finck */ 1400*c2c66affSColin Finck png_ptr->num_trans = 0; 1401*c2c66affSColin Finck } 1402*c2c66affSColin Finck #endif /* STRIP_ALPHA supported, no COMPOSE */ 1403*c2c66affSColin Finck 1404*c2c66affSColin Finck #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 1405*c2c66affSColin Finck /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA 1406*c2c66affSColin Finck * settings will have no effect. 1407*c2c66affSColin Finck */ 1408*c2c66affSColin Finck if (png_gamma_significant(png_ptr->screen_gamma) == 0) 1409*c2c66affSColin Finck { 1410*c2c66affSColin Finck png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 1411*c2c66affSColin Finck png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 1412*c2c66affSColin Finck } 1413*c2c66affSColin Finck #endif 1414*c2c66affSColin Finck 1415*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1416*c2c66affSColin Finck /* Make sure the coefficients for the rgb to gray conversion are set 1417*c2c66affSColin Finck * appropriately. 1418*c2c66affSColin Finck */ 1419*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) 1420*c2c66affSColin Finck png_colorspace_set_rgb_coefficients(png_ptr); 1421*c2c66affSColin Finck #endif 1422*c2c66affSColin Finck 1423*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1424*c2c66affSColin Finck #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1425*c2c66affSColin Finck /* Detect gray background and attempt to enable optimization for 1426*c2c66affSColin Finck * gray --> RGB case. 1427*c2c66affSColin Finck * 1428*c2c66affSColin Finck * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 1429*c2c66affSColin Finck * RGB_ALPHA (in which case need_expand is superfluous anyway), the 1430*c2c66affSColin Finck * background color might actually be gray yet not be flagged as such. 1431*c2c66affSColin Finck * This is not a problem for the current code, which uses 1432*c2c66affSColin Finck * PNG_BACKGROUND_IS_GRAY only to decide when to do the 1433*c2c66affSColin Finck * png_do_gray_to_rgb() transformation. 1434*c2c66affSColin Finck * 1435*c2c66affSColin Finck * TODO: this code needs to be revised to avoid the complexity and 1436*c2c66affSColin Finck * interdependencies. The color type of the background should be recorded in 1437*c2c66affSColin Finck * png_set_background, along with the bit depth, then the code has a record 1438*c2c66affSColin Finck * of exactly what color space the background is currently in. 1439*c2c66affSColin Finck */ 1440*c2c66affSColin Finck if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0) 1441*c2c66affSColin Finck { 1442*c2c66affSColin Finck /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if 1443*c2c66affSColin Finck * the file was grayscale the background value is gray. 1444*c2c66affSColin Finck */ 1445*c2c66affSColin Finck if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) 1446*c2c66affSColin Finck png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1447*c2c66affSColin Finck } 1448*c2c66affSColin Finck 1449*c2c66affSColin Finck else if ((png_ptr->transformations & PNG_COMPOSE) != 0) 1450*c2c66affSColin Finck { 1451*c2c66affSColin Finck /* PNG_COMPOSE: png_set_background was called with need_expand false, 1452*c2c66affSColin Finck * so the color is in the color space of the output or png_set_alpha_mode 1453*c2c66affSColin Finck * was called and the color is black. Ignore RGB_TO_GRAY because that 1454*c2c66affSColin Finck * happens before GRAY_TO_RGB. 1455*c2c66affSColin Finck */ 1456*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0) 1457*c2c66affSColin Finck { 1458*c2c66affSColin Finck if (png_ptr->background.red == png_ptr->background.green && 1459*c2c66affSColin Finck png_ptr->background.red == png_ptr->background.blue) 1460*c2c66affSColin Finck { 1461*c2c66affSColin Finck png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1462*c2c66affSColin Finck png_ptr->background.gray = png_ptr->background.red; 1463*c2c66affSColin Finck } 1464*c2c66affSColin Finck } 1465*c2c66affSColin Finck } 1466*c2c66affSColin Finck #endif /* READ_EXPAND && READ_BACKGROUND */ 1467*c2c66affSColin Finck #endif /* READ_GRAY_TO_RGB */ 1468*c2c66affSColin Finck 1469*c2c66affSColin Finck /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations 1470*c2c66affSColin Finck * can be performed directly on the palette, and some (such as rgb to gray) 1471*c2c66affSColin Finck * can be optimized inside the palette. This is particularly true of the 1472*c2c66affSColin Finck * composite (background and alpha) stuff, which can be pretty much all done 1473*c2c66affSColin Finck * in the palette even if the result is expanded to RGB or gray afterward. 1474*c2c66affSColin Finck * 1475*c2c66affSColin Finck * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and 1476*c2c66affSColin Finck * earlier and the palette stuff is actually handled on the first row. This 1477*c2c66affSColin Finck * leads to the reported bug that the palette returned by png_get_PLTE is not 1478*c2c66affSColin Finck * updated. 1479*c2c66affSColin Finck */ 1480*c2c66affSColin Finck if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1481*c2c66affSColin Finck png_init_palette_transformations(png_ptr); 1482*c2c66affSColin Finck 1483*c2c66affSColin Finck else 1484*c2c66affSColin Finck png_init_rgb_transformations(png_ptr); 1485*c2c66affSColin Finck 1486*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1487*c2c66affSColin Finck defined(PNG_READ_EXPAND_16_SUPPORTED) 1488*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_16) != 0 && 1489*c2c66affSColin Finck (png_ptr->transformations & PNG_COMPOSE) != 0 && 1490*c2c66affSColin Finck (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 && 1491*c2c66affSColin Finck png_ptr->bit_depth != 16) 1492*c2c66affSColin Finck { 1493*c2c66affSColin Finck /* TODO: fix this. Because the expand_16 operation is after the compose 1494*c2c66affSColin Finck * handling the background color must be 8, not 16, bits deep, but the 1495*c2c66affSColin Finck * application will supply a 16-bit value so reduce it here. 1496*c2c66affSColin Finck * 1497*c2c66affSColin Finck * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at 1498*c2c66affSColin Finck * present, so that case is ok (until do_expand_16 is moved.) 1499*c2c66affSColin Finck * 1500*c2c66affSColin Finck * NOTE: this discards the low 16 bits of the user supplied background 1501*c2c66affSColin Finck * color, but until expand_16 works properly there is no choice! 1502*c2c66affSColin Finck */ 1503*c2c66affSColin Finck # define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x)) 1504*c2c66affSColin Finck CHOP(png_ptr->background.red); 1505*c2c66affSColin Finck CHOP(png_ptr->background.green); 1506*c2c66affSColin Finck CHOP(png_ptr->background.blue); 1507*c2c66affSColin Finck CHOP(png_ptr->background.gray); 1508*c2c66affSColin Finck # undef CHOP 1509*c2c66affSColin Finck } 1510*c2c66affSColin Finck #endif /* READ_BACKGROUND && READ_EXPAND_16 */ 1511*c2c66affSColin Finck 1512*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1513*c2c66affSColin Finck (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ 1514*c2c66affSColin Finck defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) 1515*c2c66affSColin Finck if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 && 1516*c2c66affSColin Finck (png_ptr->transformations & PNG_COMPOSE) != 0 && 1517*c2c66affSColin Finck (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 && 1518*c2c66affSColin Finck png_ptr->bit_depth == 16) 1519*c2c66affSColin Finck { 1520*c2c66affSColin Finck /* On the other hand, if a 16-bit file is to be reduced to 8-bits per 1521*c2c66affSColin Finck * component this will also happen after PNG_COMPOSE and so the background 1522*c2c66affSColin Finck * color must be pre-expanded here. 1523*c2c66affSColin Finck * 1524*c2c66affSColin Finck * TODO: fix this too. 1525*c2c66affSColin Finck */ 1526*c2c66affSColin Finck png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); 1527*c2c66affSColin Finck png_ptr->background.green = 1528*c2c66affSColin Finck (png_uint_16)(png_ptr->background.green * 257); 1529*c2c66affSColin Finck png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); 1530*c2c66affSColin Finck png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); 1531*c2c66affSColin Finck } 1532*c2c66affSColin Finck #endif 1533*c2c66affSColin Finck 1534*c2c66affSColin Finck /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the 1535*c2c66affSColin Finck * background support (see the comments in scripts/pnglibconf.dfa), this 1536*c2c66affSColin Finck * allows pre-multiplication of the alpha channel to be implemented as 1537*c2c66affSColin Finck * compositing on black. This is probably sub-optimal and has been done in 1538*c2c66affSColin Finck * 1.5.4 betas simply to enable external critique and testing (i.e. to 1539*c2c66affSColin Finck * implement the new API quickly, without lots of internal changes.) 1540*c2c66affSColin Finck */ 1541*c2c66affSColin Finck 1542*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 1543*c2c66affSColin Finck # ifdef PNG_READ_BACKGROUND_SUPPORTED 1544*c2c66affSColin Finck /* Includes ALPHA_MODE */ 1545*c2c66affSColin Finck png_ptr->background_1 = png_ptr->background; 1546*c2c66affSColin Finck # endif 1547*c2c66affSColin Finck 1548*c2c66affSColin Finck /* This needs to change - in the palette image case a whole set of tables are 1549*c2c66affSColin Finck * built when it would be quicker to just calculate the correct value for 1550*c2c66affSColin Finck * each palette entry directly. Also, the test is too tricky - why check 1551*c2c66affSColin Finck * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that 1552*c2c66affSColin Finck * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the 1553*c2c66affSColin Finck * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction 1554*c2c66affSColin Finck * the gamma tables will not be built even if composition is required on a 1555*c2c66affSColin Finck * gamma encoded value. 1556*c2c66affSColin Finck * 1557*c2c66affSColin Finck * In 1.5.4 this is addressed below by an additional check on the individual 1558*c2c66affSColin Finck * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the 1559*c2c66affSColin Finck * tables. 1560*c2c66affSColin Finck */ 1561*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GAMMA) != 0 || 1562*c2c66affSColin Finck ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 && 1563*c2c66affSColin Finck (png_gamma_significant(png_ptr->colorspace.gamma) != 0 || 1564*c2c66affSColin Finck png_gamma_significant(png_ptr->screen_gamma) != 0)) || 1565*c2c66affSColin Finck ((png_ptr->transformations & PNG_COMPOSE) != 0 && 1566*c2c66affSColin Finck (png_gamma_significant(png_ptr->colorspace.gamma) != 0 || 1567*c2c66affSColin Finck png_gamma_significant(png_ptr->screen_gamma) != 0 1568*c2c66affSColin Finck # ifdef PNG_READ_BACKGROUND_SUPPORTED 1569*c2c66affSColin Finck || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE && 1570*c2c66affSColin Finck png_gamma_significant(png_ptr->background_gamma) != 0) 1571*c2c66affSColin Finck # endif 1572*c2c66affSColin Finck )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 && 1573*c2c66affSColin Finck png_gamma_significant(png_ptr->screen_gamma) != 0)) 1574*c2c66affSColin Finck { 1575*c2c66affSColin Finck png_build_gamma_table(png_ptr, png_ptr->bit_depth); 1576*c2c66affSColin Finck 1577*c2c66affSColin Finck #ifdef PNG_READ_BACKGROUND_SUPPORTED 1578*c2c66affSColin Finck if ((png_ptr->transformations & PNG_COMPOSE) != 0) 1579*c2c66affSColin Finck { 1580*c2c66affSColin Finck /* Issue a warning about this combination: because RGB_TO_GRAY is 1581*c2c66affSColin Finck * optimized to do the gamma transform if present yet do_background has 1582*c2c66affSColin Finck * to do the same thing if both options are set a 1583*c2c66affSColin Finck * double-gamma-correction happens. This is true in all versions of 1584*c2c66affSColin Finck * libpng to date. 1585*c2c66affSColin Finck */ 1586*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) 1587*c2c66affSColin Finck png_warning(png_ptr, 1588*c2c66affSColin Finck "libpng does not support gamma+background+rgb_to_gray"); 1589*c2c66affSColin Finck 1590*c2c66affSColin Finck if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0) 1591*c2c66affSColin Finck { 1592*c2c66affSColin Finck /* We don't get to here unless there is a tRNS chunk with non-opaque 1593*c2c66affSColin Finck * entries - see the checking code at the start of this function. 1594*c2c66affSColin Finck */ 1595*c2c66affSColin Finck png_color back, back_1; 1596*c2c66affSColin Finck png_colorp palette = png_ptr->palette; 1597*c2c66affSColin Finck int num_palette = png_ptr->num_palette; 1598*c2c66affSColin Finck int i; 1599*c2c66affSColin Finck if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 1600*c2c66affSColin Finck { 1601*c2c66affSColin Finck 1602*c2c66affSColin Finck back.red = png_ptr->gamma_table[png_ptr->background.red]; 1603*c2c66affSColin Finck back.green = png_ptr->gamma_table[png_ptr->background.green]; 1604*c2c66affSColin Finck back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 1605*c2c66affSColin Finck 1606*c2c66affSColin Finck back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 1607*c2c66affSColin Finck back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 1608*c2c66affSColin Finck back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 1609*c2c66affSColin Finck } 1610*c2c66affSColin Finck else 1611*c2c66affSColin Finck { 1612*c2c66affSColin Finck png_fixed_point g, gs; 1613*c2c66affSColin Finck 1614*c2c66affSColin Finck switch (png_ptr->background_gamma_type) 1615*c2c66affSColin Finck { 1616*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_SCREEN: 1617*c2c66affSColin Finck g = (png_ptr->screen_gamma); 1618*c2c66affSColin Finck gs = PNG_FP_1; 1619*c2c66affSColin Finck break; 1620*c2c66affSColin Finck 1621*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_FILE: 1622*c2c66affSColin Finck g = png_reciprocal(png_ptr->colorspace.gamma); 1623*c2c66affSColin Finck gs = png_reciprocal2(png_ptr->colorspace.gamma, 1624*c2c66affSColin Finck png_ptr->screen_gamma); 1625*c2c66affSColin Finck break; 1626*c2c66affSColin Finck 1627*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_UNIQUE: 1628*c2c66affSColin Finck g = png_reciprocal(png_ptr->background_gamma); 1629*c2c66affSColin Finck gs = png_reciprocal2(png_ptr->background_gamma, 1630*c2c66affSColin Finck png_ptr->screen_gamma); 1631*c2c66affSColin Finck break; 1632*c2c66affSColin Finck default: 1633*c2c66affSColin Finck g = PNG_FP_1; /* back_1 */ 1634*c2c66affSColin Finck gs = PNG_FP_1; /* back */ 1635*c2c66affSColin Finck break; 1636*c2c66affSColin Finck } 1637*c2c66affSColin Finck 1638*c2c66affSColin Finck if (png_gamma_significant(gs) != 0) 1639*c2c66affSColin Finck { 1640*c2c66affSColin Finck back.red = png_gamma_8bit_correct(png_ptr->background.red, 1641*c2c66affSColin Finck gs); 1642*c2c66affSColin Finck back.green = png_gamma_8bit_correct(png_ptr->background.green, 1643*c2c66affSColin Finck gs); 1644*c2c66affSColin Finck back.blue = png_gamma_8bit_correct(png_ptr->background.blue, 1645*c2c66affSColin Finck gs); 1646*c2c66affSColin Finck } 1647*c2c66affSColin Finck 1648*c2c66affSColin Finck else 1649*c2c66affSColin Finck { 1650*c2c66affSColin Finck back.red = (png_byte)png_ptr->background.red; 1651*c2c66affSColin Finck back.green = (png_byte)png_ptr->background.green; 1652*c2c66affSColin Finck back.blue = (png_byte)png_ptr->background.blue; 1653*c2c66affSColin Finck } 1654*c2c66affSColin Finck 1655*c2c66affSColin Finck if (png_gamma_significant(g) != 0) 1656*c2c66affSColin Finck { 1657*c2c66affSColin Finck back_1.red = png_gamma_8bit_correct(png_ptr->background.red, 1658*c2c66affSColin Finck g); 1659*c2c66affSColin Finck back_1.green = png_gamma_8bit_correct( 1660*c2c66affSColin Finck png_ptr->background.green, g); 1661*c2c66affSColin Finck back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, 1662*c2c66affSColin Finck g); 1663*c2c66affSColin Finck } 1664*c2c66affSColin Finck 1665*c2c66affSColin Finck else 1666*c2c66affSColin Finck { 1667*c2c66affSColin Finck back_1.red = (png_byte)png_ptr->background.red; 1668*c2c66affSColin Finck back_1.green = (png_byte)png_ptr->background.green; 1669*c2c66affSColin Finck back_1.blue = (png_byte)png_ptr->background.blue; 1670*c2c66affSColin Finck } 1671*c2c66affSColin Finck } 1672*c2c66affSColin Finck 1673*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 1674*c2c66affSColin Finck { 1675*c2c66affSColin Finck if (i < (int)png_ptr->num_trans && 1676*c2c66affSColin Finck png_ptr->trans_alpha[i] != 0xff) 1677*c2c66affSColin Finck { 1678*c2c66affSColin Finck if (png_ptr->trans_alpha[i] == 0) 1679*c2c66affSColin Finck { 1680*c2c66affSColin Finck palette[i] = back; 1681*c2c66affSColin Finck } 1682*c2c66affSColin Finck else /* if (png_ptr->trans_alpha[i] != 0xff) */ 1683*c2c66affSColin Finck { 1684*c2c66affSColin Finck png_byte v, w; 1685*c2c66affSColin Finck 1686*c2c66affSColin Finck v = png_ptr->gamma_to_1[palette[i].red]; 1687*c2c66affSColin Finck png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); 1688*c2c66affSColin Finck palette[i].red = png_ptr->gamma_from_1[w]; 1689*c2c66affSColin Finck 1690*c2c66affSColin Finck v = png_ptr->gamma_to_1[palette[i].green]; 1691*c2c66affSColin Finck png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); 1692*c2c66affSColin Finck palette[i].green = png_ptr->gamma_from_1[w]; 1693*c2c66affSColin Finck 1694*c2c66affSColin Finck v = png_ptr->gamma_to_1[palette[i].blue]; 1695*c2c66affSColin Finck png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); 1696*c2c66affSColin Finck palette[i].blue = png_ptr->gamma_from_1[w]; 1697*c2c66affSColin Finck } 1698*c2c66affSColin Finck } 1699*c2c66affSColin Finck else 1700*c2c66affSColin Finck { 1701*c2c66affSColin Finck palette[i].red = png_ptr->gamma_table[palette[i].red]; 1702*c2c66affSColin Finck palette[i].green = png_ptr->gamma_table[palette[i].green]; 1703*c2c66affSColin Finck palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1704*c2c66affSColin Finck } 1705*c2c66affSColin Finck } 1706*c2c66affSColin Finck 1707*c2c66affSColin Finck /* Prevent the transformations being done again. 1708*c2c66affSColin Finck * 1709*c2c66affSColin Finck * NOTE: this is highly dubious; it removes the transformations in 1710*c2c66affSColin Finck * place. This seems inconsistent with the general treatment of the 1711*c2c66affSColin Finck * transformations elsewhere. 1712*c2c66affSColin Finck */ 1713*c2c66affSColin Finck png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); 1714*c2c66affSColin Finck } /* color_type == PNG_COLOR_TYPE_PALETTE */ 1715*c2c66affSColin Finck 1716*c2c66affSColin Finck /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 1717*c2c66affSColin Finck else /* color_type != PNG_COLOR_TYPE_PALETTE */ 1718*c2c66affSColin Finck { 1719*c2c66affSColin Finck int gs_sig, g_sig; 1720*c2c66affSColin Finck png_fixed_point g = PNG_FP_1; /* Correction to linear */ 1721*c2c66affSColin Finck png_fixed_point gs = PNG_FP_1; /* Correction to screen */ 1722*c2c66affSColin Finck 1723*c2c66affSColin Finck switch (png_ptr->background_gamma_type) 1724*c2c66affSColin Finck { 1725*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_SCREEN: 1726*c2c66affSColin Finck g = png_ptr->screen_gamma; 1727*c2c66affSColin Finck /* gs = PNG_FP_1; */ 1728*c2c66affSColin Finck break; 1729*c2c66affSColin Finck 1730*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_FILE: 1731*c2c66affSColin Finck g = png_reciprocal(png_ptr->colorspace.gamma); 1732*c2c66affSColin Finck gs = png_reciprocal2(png_ptr->colorspace.gamma, 1733*c2c66affSColin Finck png_ptr->screen_gamma); 1734*c2c66affSColin Finck break; 1735*c2c66affSColin Finck 1736*c2c66affSColin Finck case PNG_BACKGROUND_GAMMA_UNIQUE: 1737*c2c66affSColin Finck g = png_reciprocal(png_ptr->background_gamma); 1738*c2c66affSColin Finck gs = png_reciprocal2(png_ptr->background_gamma, 1739*c2c66affSColin Finck png_ptr->screen_gamma); 1740*c2c66affSColin Finck break; 1741*c2c66affSColin Finck 1742*c2c66affSColin Finck default: 1743*c2c66affSColin Finck png_error(png_ptr, "invalid background gamma type"); 1744*c2c66affSColin Finck } 1745*c2c66affSColin Finck 1746*c2c66affSColin Finck g_sig = png_gamma_significant(g); 1747*c2c66affSColin Finck gs_sig = png_gamma_significant(gs); 1748*c2c66affSColin Finck 1749*c2c66affSColin Finck if (g_sig != 0) 1750*c2c66affSColin Finck png_ptr->background_1.gray = png_gamma_correct(png_ptr, 1751*c2c66affSColin Finck png_ptr->background.gray, g); 1752*c2c66affSColin Finck 1753*c2c66affSColin Finck if (gs_sig != 0) 1754*c2c66affSColin Finck png_ptr->background.gray = png_gamma_correct(png_ptr, 1755*c2c66affSColin Finck png_ptr->background.gray, gs); 1756*c2c66affSColin Finck 1757*c2c66affSColin Finck if ((png_ptr->background.red != png_ptr->background.green) || 1758*c2c66affSColin Finck (png_ptr->background.red != png_ptr->background.blue) || 1759*c2c66affSColin Finck (png_ptr->background.red != png_ptr->background.gray)) 1760*c2c66affSColin Finck { 1761*c2c66affSColin Finck /* RGB or RGBA with color background */ 1762*c2c66affSColin Finck if (g_sig != 0) 1763*c2c66affSColin Finck { 1764*c2c66affSColin Finck png_ptr->background_1.red = png_gamma_correct(png_ptr, 1765*c2c66affSColin Finck png_ptr->background.red, g); 1766*c2c66affSColin Finck 1767*c2c66affSColin Finck png_ptr->background_1.green = png_gamma_correct(png_ptr, 1768*c2c66affSColin Finck png_ptr->background.green, g); 1769*c2c66affSColin Finck 1770*c2c66affSColin Finck png_ptr->background_1.blue = png_gamma_correct(png_ptr, 1771*c2c66affSColin Finck png_ptr->background.blue, g); 1772*c2c66affSColin Finck } 1773*c2c66affSColin Finck 1774*c2c66affSColin Finck if (gs_sig != 0) 1775*c2c66affSColin Finck { 1776*c2c66affSColin Finck png_ptr->background.red = png_gamma_correct(png_ptr, 1777*c2c66affSColin Finck png_ptr->background.red, gs); 1778*c2c66affSColin Finck 1779*c2c66affSColin Finck png_ptr->background.green = png_gamma_correct(png_ptr, 1780*c2c66affSColin Finck png_ptr->background.green, gs); 1781*c2c66affSColin Finck 1782*c2c66affSColin Finck png_ptr->background.blue = png_gamma_correct(png_ptr, 1783*c2c66affSColin Finck png_ptr->background.blue, gs); 1784*c2c66affSColin Finck } 1785*c2c66affSColin Finck } 1786*c2c66affSColin Finck 1787*c2c66affSColin Finck else 1788*c2c66affSColin Finck { 1789*c2c66affSColin Finck /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 1790*c2c66affSColin Finck png_ptr->background_1.red = png_ptr->background_1.green 1791*c2c66affSColin Finck = png_ptr->background_1.blue = png_ptr->background_1.gray; 1792*c2c66affSColin Finck 1793*c2c66affSColin Finck png_ptr->background.red = png_ptr->background.green 1794*c2c66affSColin Finck = png_ptr->background.blue = png_ptr->background.gray; 1795*c2c66affSColin Finck } 1796*c2c66affSColin Finck 1797*c2c66affSColin Finck /* The background is now in screen gamma: */ 1798*c2c66affSColin Finck png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; 1799*c2c66affSColin Finck } /* color_type != PNG_COLOR_TYPE_PALETTE */ 1800*c2c66affSColin Finck }/* png_ptr->transformations & PNG_BACKGROUND */ 1801*c2c66affSColin Finck 1802*c2c66affSColin Finck else 1803*c2c66affSColin Finck /* Transformation does not include PNG_BACKGROUND */ 1804*c2c66affSColin Finck #endif /* READ_BACKGROUND */ 1805*c2c66affSColin Finck if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE 1806*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1807*c2c66affSColin Finck /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ 1808*c2c66affSColin Finck && ((png_ptr->transformations & PNG_EXPAND) == 0 || 1809*c2c66affSColin Finck (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) 1810*c2c66affSColin Finck #endif 1811*c2c66affSColin Finck ) 1812*c2c66affSColin Finck { 1813*c2c66affSColin Finck png_colorp palette = png_ptr->palette; 1814*c2c66affSColin Finck int num_palette = png_ptr->num_palette; 1815*c2c66affSColin Finck int i; 1816*c2c66affSColin Finck 1817*c2c66affSColin Finck /* NOTE: there are other transformations that should probably be in 1818*c2c66affSColin Finck * here too. 1819*c2c66affSColin Finck */ 1820*c2c66affSColin Finck for (i = 0; i < num_palette; i++) 1821*c2c66affSColin Finck { 1822*c2c66affSColin Finck palette[i].red = png_ptr->gamma_table[palette[i].red]; 1823*c2c66affSColin Finck palette[i].green = png_ptr->gamma_table[palette[i].green]; 1824*c2c66affSColin Finck palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1825*c2c66affSColin Finck } 1826*c2c66affSColin Finck 1827*c2c66affSColin Finck /* Done the gamma correction. */ 1828*c2c66affSColin Finck png_ptr->transformations &= ~PNG_GAMMA; 1829*c2c66affSColin Finck } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ 1830*c2c66affSColin Finck } 1831*c2c66affSColin Finck #ifdef PNG_READ_BACKGROUND_SUPPORTED 1832*c2c66affSColin Finck else 1833*c2c66affSColin Finck #endif 1834*c2c66affSColin Finck #endif /* READ_GAMMA */ 1835*c2c66affSColin Finck 1836*c2c66affSColin Finck #ifdef PNG_READ_BACKGROUND_SUPPORTED 1837*c2c66affSColin Finck /* No GAMMA transformation (see the hanging else 4 lines above) */ 1838*c2c66affSColin Finck if ((png_ptr->transformations & PNG_COMPOSE) != 0 && 1839*c2c66affSColin Finck (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 1840*c2c66affSColin Finck { 1841*c2c66affSColin Finck int i; 1842*c2c66affSColin Finck int istop = (int)png_ptr->num_trans; 1843*c2c66affSColin Finck png_color back; 1844*c2c66affSColin Finck png_colorp palette = png_ptr->palette; 1845*c2c66affSColin Finck 1846*c2c66affSColin Finck back.red = (png_byte)png_ptr->background.red; 1847*c2c66affSColin Finck back.green = (png_byte)png_ptr->background.green; 1848*c2c66affSColin Finck back.blue = (png_byte)png_ptr->background.blue; 1849*c2c66affSColin Finck 1850*c2c66affSColin Finck for (i = 0; i < istop; i++) 1851*c2c66affSColin Finck { 1852*c2c66affSColin Finck if (png_ptr->trans_alpha[i] == 0) 1853*c2c66affSColin Finck { 1854*c2c66affSColin Finck palette[i] = back; 1855*c2c66affSColin Finck } 1856*c2c66affSColin Finck 1857*c2c66affSColin Finck else if (png_ptr->trans_alpha[i] != 0xff) 1858*c2c66affSColin Finck { 1859*c2c66affSColin Finck /* The png_composite() macro is defined in png.h */ 1860*c2c66affSColin Finck png_composite(palette[i].red, palette[i].red, 1861*c2c66affSColin Finck png_ptr->trans_alpha[i], back.red); 1862*c2c66affSColin Finck 1863*c2c66affSColin Finck png_composite(palette[i].green, palette[i].green, 1864*c2c66affSColin Finck png_ptr->trans_alpha[i], back.green); 1865*c2c66affSColin Finck 1866*c2c66affSColin Finck png_composite(palette[i].blue, palette[i].blue, 1867*c2c66affSColin Finck png_ptr->trans_alpha[i], back.blue); 1868*c2c66affSColin Finck } 1869*c2c66affSColin Finck } 1870*c2c66affSColin Finck 1871*c2c66affSColin Finck png_ptr->transformations &= ~PNG_COMPOSE; 1872*c2c66affSColin Finck } 1873*c2c66affSColin Finck #endif /* READ_BACKGROUND */ 1874*c2c66affSColin Finck 1875*c2c66affSColin Finck #ifdef PNG_READ_SHIFT_SUPPORTED 1876*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SHIFT) != 0 && 1877*c2c66affSColin Finck (png_ptr->transformations & PNG_EXPAND) == 0 && 1878*c2c66affSColin Finck (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 1879*c2c66affSColin Finck { 1880*c2c66affSColin Finck int i; 1881*c2c66affSColin Finck int istop = png_ptr->num_palette; 1882*c2c66affSColin Finck int shift = 8 - png_ptr->sig_bit.red; 1883*c2c66affSColin Finck 1884*c2c66affSColin Finck png_ptr->transformations &= ~PNG_SHIFT; 1885*c2c66affSColin Finck 1886*c2c66affSColin Finck /* significant bits can be in the range 1 to 7 for a meaninful result, if 1887*c2c66affSColin Finck * the number of significant bits is 0 then no shift is done (this is an 1888*c2c66affSColin Finck * error condition which is silently ignored.) 1889*c2c66affSColin Finck */ 1890*c2c66affSColin Finck if (shift > 0 && shift < 8) 1891*c2c66affSColin Finck for (i=0; i<istop; ++i) 1892*c2c66affSColin Finck { 1893*c2c66affSColin Finck int component = png_ptr->palette[i].red; 1894*c2c66affSColin Finck 1895*c2c66affSColin Finck component >>= shift; 1896*c2c66affSColin Finck png_ptr->palette[i].red = (png_byte)component; 1897*c2c66affSColin Finck } 1898*c2c66affSColin Finck 1899*c2c66affSColin Finck shift = 8 - png_ptr->sig_bit.green; 1900*c2c66affSColin Finck if (shift > 0 && shift < 8) 1901*c2c66affSColin Finck for (i=0; i<istop; ++i) 1902*c2c66affSColin Finck { 1903*c2c66affSColin Finck int component = png_ptr->palette[i].green; 1904*c2c66affSColin Finck 1905*c2c66affSColin Finck component >>= shift; 1906*c2c66affSColin Finck png_ptr->palette[i].green = (png_byte)component; 1907*c2c66affSColin Finck } 1908*c2c66affSColin Finck 1909*c2c66affSColin Finck shift = 8 - png_ptr->sig_bit.blue; 1910*c2c66affSColin Finck if (shift > 0 && shift < 8) 1911*c2c66affSColin Finck for (i=0; i<istop; ++i) 1912*c2c66affSColin Finck { 1913*c2c66affSColin Finck int component = png_ptr->palette[i].blue; 1914*c2c66affSColin Finck 1915*c2c66affSColin Finck component >>= shift; 1916*c2c66affSColin Finck png_ptr->palette[i].blue = (png_byte)component; 1917*c2c66affSColin Finck } 1918*c2c66affSColin Finck } 1919*c2c66affSColin Finck #endif /* READ_SHIFT */ 1920*c2c66affSColin Finck } 1921*c2c66affSColin Finck 1922*c2c66affSColin Finck /* Modify the info structure to reflect the transformations. The 1923*c2c66affSColin Finck * info should be updated so a PNG file could be written with it, 1924*c2c66affSColin Finck * assuming the transformations result in valid PNG data. 1925*c2c66affSColin Finck */ 1926*c2c66affSColin Finck void /* PRIVATE */ 1927*c2c66affSColin Finck png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) 1928*c2c66affSColin Finck { 1929*c2c66affSColin Finck png_debug(1, "in png_read_transform_info"); 1930*c2c66affSColin Finck 1931*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_SUPPORTED 1932*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND) != 0) 1933*c2c66affSColin Finck { 1934*c2c66affSColin Finck if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1935*c2c66affSColin Finck { 1936*c2c66affSColin Finck /* This check must match what actually happens in 1937*c2c66affSColin Finck * png_do_expand_palette; if it ever checks the tRNS chunk to see if 1938*c2c66affSColin Finck * it is all opaque we must do the same (at present it does not.) 1939*c2c66affSColin Finck */ 1940*c2c66affSColin Finck if (png_ptr->num_trans > 0) 1941*c2c66affSColin Finck info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1942*c2c66affSColin Finck 1943*c2c66affSColin Finck else 1944*c2c66affSColin Finck info_ptr->color_type = PNG_COLOR_TYPE_RGB; 1945*c2c66affSColin Finck 1946*c2c66affSColin Finck info_ptr->bit_depth = 8; 1947*c2c66affSColin Finck info_ptr->num_trans = 0; 1948*c2c66affSColin Finck 1949*c2c66affSColin Finck if (png_ptr->palette == NULL) 1950*c2c66affSColin Finck png_error (png_ptr, "Palette is NULL in indexed image"); 1951*c2c66affSColin Finck } 1952*c2c66affSColin Finck else 1953*c2c66affSColin Finck { 1954*c2c66affSColin Finck if (png_ptr->num_trans != 0) 1955*c2c66affSColin Finck { 1956*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0) 1957*c2c66affSColin Finck info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1958*c2c66affSColin Finck } 1959*c2c66affSColin Finck if (info_ptr->bit_depth < 8) 1960*c2c66affSColin Finck info_ptr->bit_depth = 8; 1961*c2c66affSColin Finck 1962*c2c66affSColin Finck info_ptr->num_trans = 0; 1963*c2c66affSColin Finck } 1964*c2c66affSColin Finck } 1965*c2c66affSColin Finck #endif 1966*c2c66affSColin Finck 1967*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 1968*c2c66affSColin Finck defined(PNG_READ_ALPHA_MODE_SUPPORTED) 1969*c2c66affSColin Finck /* The following is almost certainly wrong unless the background value is in 1970*c2c66affSColin Finck * the screen space! 1971*c2c66affSColin Finck */ 1972*c2c66affSColin Finck if ((png_ptr->transformations & PNG_COMPOSE) != 0) 1973*c2c66affSColin Finck info_ptr->background = png_ptr->background; 1974*c2c66affSColin Finck #endif 1975*c2c66affSColin Finck 1976*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 1977*c2c66affSColin Finck /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), 1978*c2c66affSColin Finck * however it seems that the code in png_init_read_transformations, which has 1979*c2c66affSColin Finck * been called before this from png_read_update_info->png_read_start_row 1980*c2c66affSColin Finck * sometimes does the gamma transform and cancels the flag. 1981*c2c66affSColin Finck * 1982*c2c66affSColin Finck * TODO: this looks wrong; the info_ptr should end up with a gamma equal to 1983*c2c66affSColin Finck * the screen_gamma value. The following probably results in weirdness if 1984*c2c66affSColin Finck * the info_ptr is used by the app after the rows have been read. 1985*c2c66affSColin Finck */ 1986*c2c66affSColin Finck info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; 1987*c2c66affSColin Finck #endif 1988*c2c66affSColin Finck 1989*c2c66affSColin Finck if (info_ptr->bit_depth == 16) 1990*c2c66affSColin Finck { 1991*c2c66affSColin Finck # ifdef PNG_READ_16BIT_SUPPORTED 1992*c2c66affSColin Finck # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1993*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0) 1994*c2c66affSColin Finck info_ptr->bit_depth = 8; 1995*c2c66affSColin Finck # endif 1996*c2c66affSColin Finck 1997*c2c66affSColin Finck # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1998*c2c66affSColin Finck if ((png_ptr->transformations & PNG_16_TO_8) != 0) 1999*c2c66affSColin Finck info_ptr->bit_depth = 8; 2000*c2c66affSColin Finck # endif 2001*c2c66affSColin Finck 2002*c2c66affSColin Finck # else 2003*c2c66affSColin Finck /* No 16-bit support: force chopping 16-bit input down to 8, in this case 2004*c2c66affSColin Finck * the app program can chose if both APIs are available by setting the 2005*c2c66affSColin Finck * correct scaling to use. 2006*c2c66affSColin Finck */ 2007*c2c66affSColin Finck # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 2008*c2c66affSColin Finck /* For compatibility with previous versions use the strip method by 2009*c2c66affSColin Finck * default. This code works because if PNG_SCALE_16_TO_8 is already 2010*c2c66affSColin Finck * set the code below will do that in preference to the chop. 2011*c2c66affSColin Finck */ 2012*c2c66affSColin Finck png_ptr->transformations |= PNG_16_TO_8; 2013*c2c66affSColin Finck info_ptr->bit_depth = 8; 2014*c2c66affSColin Finck # else 2015*c2c66affSColin Finck 2016*c2c66affSColin Finck # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 2017*c2c66affSColin Finck png_ptr->transformations |= PNG_SCALE_16_TO_8; 2018*c2c66affSColin Finck info_ptr->bit_depth = 8; 2019*c2c66affSColin Finck # else 2020*c2c66affSColin Finck 2021*c2c66affSColin Finck CONFIGURATION ERROR: you must enable at least one 16 to 8 method 2022*c2c66affSColin Finck # endif 2023*c2c66affSColin Finck # endif 2024*c2c66affSColin Finck #endif /* !READ_16BIT */ 2025*c2c66affSColin Finck } 2026*c2c66affSColin Finck 2027*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 2028*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0) 2029*c2c66affSColin Finck info_ptr->color_type = (png_byte)(info_ptr->color_type | 2030*c2c66affSColin Finck PNG_COLOR_MASK_COLOR); 2031*c2c66affSColin Finck #endif 2032*c2c66affSColin Finck 2033*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2034*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) 2035*c2c66affSColin Finck info_ptr->color_type = (png_byte)(info_ptr->color_type & 2036*c2c66affSColin Finck ~PNG_COLOR_MASK_COLOR); 2037*c2c66affSColin Finck #endif 2038*c2c66affSColin Finck 2039*c2c66affSColin Finck #ifdef PNG_READ_QUANTIZE_SUPPORTED 2040*c2c66affSColin Finck if ((png_ptr->transformations & PNG_QUANTIZE) != 0) 2041*c2c66affSColin Finck { 2042*c2c66affSColin Finck if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 2043*c2c66affSColin Finck (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 2044*c2c66affSColin Finck png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8) 2045*c2c66affSColin Finck { 2046*c2c66affSColin Finck info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 2047*c2c66affSColin Finck } 2048*c2c66affSColin Finck } 2049*c2c66affSColin Finck #endif 2050*c2c66affSColin Finck 2051*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_16_SUPPORTED 2052*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_16) != 0 && 2053*c2c66affSColin Finck info_ptr->bit_depth == 8 && 2054*c2c66affSColin Finck info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) 2055*c2c66affSColin Finck { 2056*c2c66affSColin Finck info_ptr->bit_depth = 16; 2057*c2c66affSColin Finck } 2058*c2c66affSColin Finck #endif 2059*c2c66affSColin Finck 2060*c2c66affSColin Finck #ifdef PNG_READ_PACK_SUPPORTED 2061*c2c66affSColin Finck if ((png_ptr->transformations & PNG_PACK) != 0 && 2062*c2c66affSColin Finck (info_ptr->bit_depth < 8)) 2063*c2c66affSColin Finck info_ptr->bit_depth = 8; 2064*c2c66affSColin Finck #endif 2065*c2c66affSColin Finck 2066*c2c66affSColin Finck if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 2067*c2c66affSColin Finck info_ptr->channels = 1; 2068*c2c66affSColin Finck 2069*c2c66affSColin Finck else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) 2070*c2c66affSColin Finck info_ptr->channels = 3; 2071*c2c66affSColin Finck 2072*c2c66affSColin Finck else 2073*c2c66affSColin Finck info_ptr->channels = 1; 2074*c2c66affSColin Finck 2075*c2c66affSColin Finck #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 2076*c2c66affSColin Finck if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0) 2077*c2c66affSColin Finck { 2078*c2c66affSColin Finck info_ptr->color_type = (png_byte)(info_ptr->color_type & 2079*c2c66affSColin Finck ~PNG_COLOR_MASK_ALPHA); 2080*c2c66affSColin Finck info_ptr->num_trans = 0; 2081*c2c66affSColin Finck } 2082*c2c66affSColin Finck #endif 2083*c2c66affSColin Finck 2084*c2c66affSColin Finck if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0) 2085*c2c66affSColin Finck info_ptr->channels++; 2086*c2c66affSColin Finck 2087*c2c66affSColin Finck #ifdef PNG_READ_FILLER_SUPPORTED 2088*c2c66affSColin Finck /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 2089*c2c66affSColin Finck if ((png_ptr->transformations & PNG_FILLER) != 0 && 2090*c2c66affSColin Finck (info_ptr->color_type == PNG_COLOR_TYPE_RGB || 2091*c2c66affSColin Finck info_ptr->color_type == PNG_COLOR_TYPE_GRAY)) 2092*c2c66affSColin Finck { 2093*c2c66affSColin Finck info_ptr->channels++; 2094*c2c66affSColin Finck /* If adding a true alpha channel not just filler */ 2095*c2c66affSColin Finck if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0) 2096*c2c66affSColin Finck info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 2097*c2c66affSColin Finck } 2098*c2c66affSColin Finck #endif 2099*c2c66affSColin Finck 2100*c2c66affSColin Finck #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 2101*c2c66affSColin Finck defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 2102*c2c66affSColin Finck if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) 2103*c2c66affSColin Finck { 2104*c2c66affSColin Finck if (png_ptr->user_transform_depth != 0) 2105*c2c66affSColin Finck info_ptr->bit_depth = png_ptr->user_transform_depth; 2106*c2c66affSColin Finck 2107*c2c66affSColin Finck if (png_ptr->user_transform_channels != 0) 2108*c2c66affSColin Finck info_ptr->channels = png_ptr->user_transform_channels; 2109*c2c66affSColin Finck } 2110*c2c66affSColin Finck #endif 2111*c2c66affSColin Finck 2112*c2c66affSColin Finck info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 2113*c2c66affSColin Finck info_ptr->bit_depth); 2114*c2c66affSColin Finck 2115*c2c66affSColin Finck info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 2116*c2c66affSColin Finck 2117*c2c66affSColin Finck /* Adding in 1.5.4: cache the above value in png_struct so that we can later 2118*c2c66affSColin Finck * check in png_rowbytes that the user buffer won't get overwritten. Note 2119*c2c66affSColin Finck * that the field is not always set - if png_read_update_info isn't called 2120*c2c66affSColin Finck * the application has to either not do any transforms or get the calculation 2121*c2c66affSColin Finck * right itself. 2122*c2c66affSColin Finck */ 2123*c2c66affSColin Finck png_ptr->info_rowbytes = info_ptr->rowbytes; 2124*c2c66affSColin Finck 2125*c2c66affSColin Finck #ifndef PNG_READ_EXPAND_SUPPORTED 2126*c2c66affSColin Finck if (png_ptr != NULL) 2127*c2c66affSColin Finck return; 2128*c2c66affSColin Finck #endif 2129*c2c66affSColin Finck } 2130*c2c66affSColin Finck 2131*c2c66affSColin Finck #ifdef PNG_READ_PACK_SUPPORTED 2132*c2c66affSColin Finck /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 2133*c2c66affSColin Finck * without changing the actual values. Thus, if you had a row with 2134*c2c66affSColin Finck * a bit depth of 1, you would end up with bytes that only contained 2135*c2c66affSColin Finck * the numbers 0 or 1. If you would rather they contain 0 and 255, use 2136*c2c66affSColin Finck * png_do_shift() after this. 2137*c2c66affSColin Finck */ 2138*c2c66affSColin Finck static void 2139*c2c66affSColin Finck png_do_unpack(png_row_infop row_info, png_bytep row) 2140*c2c66affSColin Finck { 2141*c2c66affSColin Finck png_debug(1, "in png_do_unpack"); 2142*c2c66affSColin Finck 2143*c2c66affSColin Finck if (row_info->bit_depth < 8) 2144*c2c66affSColin Finck { 2145*c2c66affSColin Finck png_uint_32 i; 2146*c2c66affSColin Finck png_uint_32 row_width=row_info->width; 2147*c2c66affSColin Finck 2148*c2c66affSColin Finck switch (row_info->bit_depth) 2149*c2c66affSColin Finck { 2150*c2c66affSColin Finck case 1: 2151*c2c66affSColin Finck { 2152*c2c66affSColin Finck png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 2153*c2c66affSColin Finck png_bytep dp = row + (png_size_t)row_width - 1; 2154*c2c66affSColin Finck png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); 2155*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2156*c2c66affSColin Finck { 2157*c2c66affSColin Finck *dp = (png_byte)((*sp >> shift) & 0x01); 2158*c2c66affSColin Finck 2159*c2c66affSColin Finck if (shift == 7) 2160*c2c66affSColin Finck { 2161*c2c66affSColin Finck shift = 0; 2162*c2c66affSColin Finck sp--; 2163*c2c66affSColin Finck } 2164*c2c66affSColin Finck 2165*c2c66affSColin Finck else 2166*c2c66affSColin Finck shift++; 2167*c2c66affSColin Finck 2168*c2c66affSColin Finck dp--; 2169*c2c66affSColin Finck } 2170*c2c66affSColin Finck break; 2171*c2c66affSColin Finck } 2172*c2c66affSColin Finck 2173*c2c66affSColin Finck case 2: 2174*c2c66affSColin Finck { 2175*c2c66affSColin Finck 2176*c2c66affSColin Finck png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 2177*c2c66affSColin Finck png_bytep dp = row + (png_size_t)row_width - 1; 2178*c2c66affSColin Finck png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); 2179*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2180*c2c66affSColin Finck { 2181*c2c66affSColin Finck *dp = (png_byte)((*sp >> shift) & 0x03); 2182*c2c66affSColin Finck 2183*c2c66affSColin Finck if (shift == 6) 2184*c2c66affSColin Finck { 2185*c2c66affSColin Finck shift = 0; 2186*c2c66affSColin Finck sp--; 2187*c2c66affSColin Finck } 2188*c2c66affSColin Finck 2189*c2c66affSColin Finck else 2190*c2c66affSColin Finck shift += 2; 2191*c2c66affSColin Finck 2192*c2c66affSColin Finck dp--; 2193*c2c66affSColin Finck } 2194*c2c66affSColin Finck break; 2195*c2c66affSColin Finck } 2196*c2c66affSColin Finck 2197*c2c66affSColin Finck case 4: 2198*c2c66affSColin Finck { 2199*c2c66affSColin Finck png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 2200*c2c66affSColin Finck png_bytep dp = row + (png_size_t)row_width - 1; 2201*c2c66affSColin Finck png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); 2202*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2203*c2c66affSColin Finck { 2204*c2c66affSColin Finck *dp = (png_byte)((*sp >> shift) & 0x0f); 2205*c2c66affSColin Finck 2206*c2c66affSColin Finck if (shift == 4) 2207*c2c66affSColin Finck { 2208*c2c66affSColin Finck shift = 0; 2209*c2c66affSColin Finck sp--; 2210*c2c66affSColin Finck } 2211*c2c66affSColin Finck 2212*c2c66affSColin Finck else 2213*c2c66affSColin Finck shift = 4; 2214*c2c66affSColin Finck 2215*c2c66affSColin Finck dp--; 2216*c2c66affSColin Finck } 2217*c2c66affSColin Finck break; 2218*c2c66affSColin Finck } 2219*c2c66affSColin Finck 2220*c2c66affSColin Finck default: 2221*c2c66affSColin Finck break; 2222*c2c66affSColin Finck } 2223*c2c66affSColin Finck row_info->bit_depth = 8; 2224*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(8 * row_info->channels); 2225*c2c66affSColin Finck row_info->rowbytes = row_width * row_info->channels; 2226*c2c66affSColin Finck } 2227*c2c66affSColin Finck } 2228*c2c66affSColin Finck #endif 2229*c2c66affSColin Finck 2230*c2c66affSColin Finck #ifdef PNG_READ_SHIFT_SUPPORTED 2231*c2c66affSColin Finck /* Reverse the effects of png_do_shift. This routine merely shifts the 2232*c2c66affSColin Finck * pixels back to their significant bits values. Thus, if you have 2233*c2c66affSColin Finck * a row of bit depth 8, but only 5 are significant, this will shift 2234*c2c66affSColin Finck * the values back to 0 through 31. 2235*c2c66affSColin Finck */ 2236*c2c66affSColin Finck static void 2237*c2c66affSColin Finck png_do_unshift(png_row_infop row_info, png_bytep row, 2238*c2c66affSColin Finck png_const_color_8p sig_bits) 2239*c2c66affSColin Finck { 2240*c2c66affSColin Finck int color_type; 2241*c2c66affSColin Finck 2242*c2c66affSColin Finck png_debug(1, "in png_do_unshift"); 2243*c2c66affSColin Finck 2244*c2c66affSColin Finck /* The palette case has already been handled in the _init routine. */ 2245*c2c66affSColin Finck color_type = row_info->color_type; 2246*c2c66affSColin Finck 2247*c2c66affSColin Finck if (color_type != PNG_COLOR_TYPE_PALETTE) 2248*c2c66affSColin Finck { 2249*c2c66affSColin Finck int shift[4]; 2250*c2c66affSColin Finck int channels = 0; 2251*c2c66affSColin Finck int bit_depth = row_info->bit_depth; 2252*c2c66affSColin Finck 2253*c2c66affSColin Finck if ((color_type & PNG_COLOR_MASK_COLOR) != 0) 2254*c2c66affSColin Finck { 2255*c2c66affSColin Finck shift[channels++] = bit_depth - sig_bits->red; 2256*c2c66affSColin Finck shift[channels++] = bit_depth - sig_bits->green; 2257*c2c66affSColin Finck shift[channels++] = bit_depth - sig_bits->blue; 2258*c2c66affSColin Finck } 2259*c2c66affSColin Finck 2260*c2c66affSColin Finck else 2261*c2c66affSColin Finck { 2262*c2c66affSColin Finck shift[channels++] = bit_depth - sig_bits->gray; 2263*c2c66affSColin Finck } 2264*c2c66affSColin Finck 2265*c2c66affSColin Finck if ((color_type & PNG_COLOR_MASK_ALPHA) != 0) 2266*c2c66affSColin Finck { 2267*c2c66affSColin Finck shift[channels++] = bit_depth - sig_bits->alpha; 2268*c2c66affSColin Finck } 2269*c2c66affSColin Finck 2270*c2c66affSColin Finck { 2271*c2c66affSColin Finck int c, have_shift; 2272*c2c66affSColin Finck 2273*c2c66affSColin Finck for (c = have_shift = 0; c < channels; ++c) 2274*c2c66affSColin Finck { 2275*c2c66affSColin Finck /* A shift of more than the bit depth is an error condition but it 2276*c2c66affSColin Finck * gets ignored here. 2277*c2c66affSColin Finck */ 2278*c2c66affSColin Finck if (shift[c] <= 0 || shift[c] >= bit_depth) 2279*c2c66affSColin Finck shift[c] = 0; 2280*c2c66affSColin Finck 2281*c2c66affSColin Finck else 2282*c2c66affSColin Finck have_shift = 1; 2283*c2c66affSColin Finck } 2284*c2c66affSColin Finck 2285*c2c66affSColin Finck if (have_shift == 0) 2286*c2c66affSColin Finck return; 2287*c2c66affSColin Finck } 2288*c2c66affSColin Finck 2289*c2c66affSColin Finck switch (bit_depth) 2290*c2c66affSColin Finck { 2291*c2c66affSColin Finck default: 2292*c2c66affSColin Finck /* Must be 1bpp gray: should not be here! */ 2293*c2c66affSColin Finck /* NOTREACHED */ 2294*c2c66affSColin Finck break; 2295*c2c66affSColin Finck 2296*c2c66affSColin Finck case 2: 2297*c2c66affSColin Finck /* Must be 2bpp gray */ 2298*c2c66affSColin Finck /* assert(channels == 1 && shift[0] == 1) */ 2299*c2c66affSColin Finck { 2300*c2c66affSColin Finck png_bytep bp = row; 2301*c2c66affSColin Finck png_bytep bp_end = bp + row_info->rowbytes; 2302*c2c66affSColin Finck 2303*c2c66affSColin Finck while (bp < bp_end) 2304*c2c66affSColin Finck { 2305*c2c66affSColin Finck int b = (*bp >> 1) & 0x55; 2306*c2c66affSColin Finck *bp++ = (png_byte)b; 2307*c2c66affSColin Finck } 2308*c2c66affSColin Finck break; 2309*c2c66affSColin Finck } 2310*c2c66affSColin Finck 2311*c2c66affSColin Finck case 4: 2312*c2c66affSColin Finck /* Must be 4bpp gray */ 2313*c2c66affSColin Finck /* assert(channels == 1) */ 2314*c2c66affSColin Finck { 2315*c2c66affSColin Finck png_bytep bp = row; 2316*c2c66affSColin Finck png_bytep bp_end = bp + row_info->rowbytes; 2317*c2c66affSColin Finck int gray_shift = shift[0]; 2318*c2c66affSColin Finck int mask = 0xf >> gray_shift; 2319*c2c66affSColin Finck 2320*c2c66affSColin Finck mask |= mask << 4; 2321*c2c66affSColin Finck 2322*c2c66affSColin Finck while (bp < bp_end) 2323*c2c66affSColin Finck { 2324*c2c66affSColin Finck int b = (*bp >> gray_shift) & mask; 2325*c2c66affSColin Finck *bp++ = (png_byte)b; 2326*c2c66affSColin Finck } 2327*c2c66affSColin Finck break; 2328*c2c66affSColin Finck } 2329*c2c66affSColin Finck 2330*c2c66affSColin Finck case 8: 2331*c2c66affSColin Finck /* Single byte components, G, GA, RGB, RGBA */ 2332*c2c66affSColin Finck { 2333*c2c66affSColin Finck png_bytep bp = row; 2334*c2c66affSColin Finck png_bytep bp_end = bp + row_info->rowbytes; 2335*c2c66affSColin Finck int channel = 0; 2336*c2c66affSColin Finck 2337*c2c66affSColin Finck while (bp < bp_end) 2338*c2c66affSColin Finck { 2339*c2c66affSColin Finck int b = *bp >> shift[channel]; 2340*c2c66affSColin Finck if (++channel >= channels) 2341*c2c66affSColin Finck channel = 0; 2342*c2c66affSColin Finck *bp++ = (png_byte)b; 2343*c2c66affSColin Finck } 2344*c2c66affSColin Finck break; 2345*c2c66affSColin Finck } 2346*c2c66affSColin Finck 2347*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2348*c2c66affSColin Finck case 16: 2349*c2c66affSColin Finck /* Double byte components, G, GA, RGB, RGBA */ 2350*c2c66affSColin Finck { 2351*c2c66affSColin Finck png_bytep bp = row; 2352*c2c66affSColin Finck png_bytep bp_end = bp + row_info->rowbytes; 2353*c2c66affSColin Finck int channel = 0; 2354*c2c66affSColin Finck 2355*c2c66affSColin Finck while (bp < bp_end) 2356*c2c66affSColin Finck { 2357*c2c66affSColin Finck int value = (bp[0] << 8) + bp[1]; 2358*c2c66affSColin Finck 2359*c2c66affSColin Finck value >>= shift[channel]; 2360*c2c66affSColin Finck if (++channel >= channels) 2361*c2c66affSColin Finck channel = 0; 2362*c2c66affSColin Finck *bp++ = (png_byte)(value >> 8); 2363*c2c66affSColin Finck *bp++ = (png_byte)value; 2364*c2c66affSColin Finck } 2365*c2c66affSColin Finck break; 2366*c2c66affSColin Finck } 2367*c2c66affSColin Finck #endif 2368*c2c66affSColin Finck } 2369*c2c66affSColin Finck } 2370*c2c66affSColin Finck } 2371*c2c66affSColin Finck #endif 2372*c2c66affSColin Finck 2373*c2c66affSColin Finck #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 2374*c2c66affSColin Finck /* Scale rows of bit depth 16 down to 8 accurately */ 2375*c2c66affSColin Finck static void 2376*c2c66affSColin Finck png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) 2377*c2c66affSColin Finck { 2378*c2c66affSColin Finck png_debug(1, "in png_do_scale_16_to_8"); 2379*c2c66affSColin Finck 2380*c2c66affSColin Finck if (row_info->bit_depth == 16) 2381*c2c66affSColin Finck { 2382*c2c66affSColin Finck png_bytep sp = row; /* source */ 2383*c2c66affSColin Finck png_bytep dp = row; /* destination */ 2384*c2c66affSColin Finck png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 2385*c2c66affSColin Finck 2386*c2c66affSColin Finck while (sp < ep) 2387*c2c66affSColin Finck { 2388*c2c66affSColin Finck /* The input is an array of 16-bit components, these must be scaled to 2389*c2c66affSColin Finck * 8 bits each. For a 16-bit value V the required value (from the PNG 2390*c2c66affSColin Finck * specification) is: 2391*c2c66affSColin Finck * 2392*c2c66affSColin Finck * (V * 255) / 65535 2393*c2c66affSColin Finck * 2394*c2c66affSColin Finck * This reduces to round(V / 257), or floor((V + 128.5)/257) 2395*c2c66affSColin Finck * 2396*c2c66affSColin Finck * Represent V as the two byte value vhi.vlo. Make a guess that the 2397*c2c66affSColin Finck * result is the top byte of V, vhi, then the correction to this value 2398*c2c66affSColin Finck * is: 2399*c2c66affSColin Finck * 2400*c2c66affSColin Finck * error = floor(((V-vhi.vhi) + 128.5) / 257) 2401*c2c66affSColin Finck * = floor(((vlo-vhi) + 128.5) / 257) 2402*c2c66affSColin Finck * 2403*c2c66affSColin Finck * This can be approximated using integer arithmetic (and a signed 2404*c2c66affSColin Finck * shift): 2405*c2c66affSColin Finck * 2406*c2c66affSColin Finck * error = (vlo-vhi+128) >> 8; 2407*c2c66affSColin Finck * 2408*c2c66affSColin Finck * The approximate differs from the exact answer only when (vlo-vhi) is 2409*c2c66affSColin Finck * 128; it then gives a correction of +1 when the exact correction is 2410*c2c66affSColin Finck * 0. This gives 128 errors. The exact answer (correct for all 16-bit 2411*c2c66affSColin Finck * input values) is: 2412*c2c66affSColin Finck * 2413*c2c66affSColin Finck * error = (vlo-vhi+128)*65535 >> 24; 2414*c2c66affSColin Finck * 2415*c2c66affSColin Finck * An alternative arithmetic calculation which also gives no errors is: 2416*c2c66affSColin Finck * 2417*c2c66affSColin Finck * (V * 255 + 32895) >> 16 2418*c2c66affSColin Finck */ 2419*c2c66affSColin Finck 2420*c2c66affSColin Finck png_int_32 tmp = *sp++; /* must be signed! */ 2421*c2c66affSColin Finck tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; 2422*c2c66affSColin Finck *dp++ = (png_byte)tmp; 2423*c2c66affSColin Finck } 2424*c2c66affSColin Finck 2425*c2c66affSColin Finck row_info->bit_depth = 8; 2426*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(8 * row_info->channels); 2427*c2c66affSColin Finck row_info->rowbytes = row_info->width * row_info->channels; 2428*c2c66affSColin Finck } 2429*c2c66affSColin Finck } 2430*c2c66affSColin Finck #endif 2431*c2c66affSColin Finck 2432*c2c66affSColin Finck #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 2433*c2c66affSColin Finck static void 2434*c2c66affSColin Finck /* Simply discard the low byte. This was the default behavior prior 2435*c2c66affSColin Finck * to libpng-1.5.4. 2436*c2c66affSColin Finck */ 2437*c2c66affSColin Finck png_do_chop(png_row_infop row_info, png_bytep row) 2438*c2c66affSColin Finck { 2439*c2c66affSColin Finck png_debug(1, "in png_do_chop"); 2440*c2c66affSColin Finck 2441*c2c66affSColin Finck if (row_info->bit_depth == 16) 2442*c2c66affSColin Finck { 2443*c2c66affSColin Finck png_bytep sp = row; /* source */ 2444*c2c66affSColin Finck png_bytep dp = row; /* destination */ 2445*c2c66affSColin Finck png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 2446*c2c66affSColin Finck 2447*c2c66affSColin Finck while (sp < ep) 2448*c2c66affSColin Finck { 2449*c2c66affSColin Finck *dp++ = *sp; 2450*c2c66affSColin Finck sp += 2; /* skip low byte */ 2451*c2c66affSColin Finck } 2452*c2c66affSColin Finck 2453*c2c66affSColin Finck row_info->bit_depth = 8; 2454*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(8 * row_info->channels); 2455*c2c66affSColin Finck row_info->rowbytes = row_info->width * row_info->channels; 2456*c2c66affSColin Finck } 2457*c2c66affSColin Finck } 2458*c2c66affSColin Finck #endif 2459*c2c66affSColin Finck 2460*c2c66affSColin Finck #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 2461*c2c66affSColin Finck static void 2462*c2c66affSColin Finck png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 2463*c2c66affSColin Finck { 2464*c2c66affSColin Finck png_debug(1, "in png_do_read_swap_alpha"); 2465*c2c66affSColin Finck 2466*c2c66affSColin Finck { 2467*c2c66affSColin Finck png_uint_32 row_width = row_info->width; 2468*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 2469*c2c66affSColin Finck { 2470*c2c66affSColin Finck /* This converts from RGBA to ARGB */ 2471*c2c66affSColin Finck if (row_info->bit_depth == 8) 2472*c2c66affSColin Finck { 2473*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2474*c2c66affSColin Finck png_bytep dp = sp; 2475*c2c66affSColin Finck png_byte save; 2476*c2c66affSColin Finck png_uint_32 i; 2477*c2c66affSColin Finck 2478*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2479*c2c66affSColin Finck { 2480*c2c66affSColin Finck save = *(--sp); 2481*c2c66affSColin Finck *(--dp) = *(--sp); 2482*c2c66affSColin Finck *(--dp) = *(--sp); 2483*c2c66affSColin Finck *(--dp) = *(--sp); 2484*c2c66affSColin Finck *(--dp) = save; 2485*c2c66affSColin Finck } 2486*c2c66affSColin Finck } 2487*c2c66affSColin Finck 2488*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2489*c2c66affSColin Finck /* This converts from RRGGBBAA to AARRGGBB */ 2490*c2c66affSColin Finck else 2491*c2c66affSColin Finck { 2492*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2493*c2c66affSColin Finck png_bytep dp = sp; 2494*c2c66affSColin Finck png_byte save[2]; 2495*c2c66affSColin Finck png_uint_32 i; 2496*c2c66affSColin Finck 2497*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2498*c2c66affSColin Finck { 2499*c2c66affSColin Finck save[0] = *(--sp); 2500*c2c66affSColin Finck save[1] = *(--sp); 2501*c2c66affSColin Finck *(--dp) = *(--sp); 2502*c2c66affSColin Finck *(--dp) = *(--sp); 2503*c2c66affSColin Finck *(--dp) = *(--sp); 2504*c2c66affSColin Finck *(--dp) = *(--sp); 2505*c2c66affSColin Finck *(--dp) = *(--sp); 2506*c2c66affSColin Finck *(--dp) = *(--sp); 2507*c2c66affSColin Finck *(--dp) = save[0]; 2508*c2c66affSColin Finck *(--dp) = save[1]; 2509*c2c66affSColin Finck } 2510*c2c66affSColin Finck } 2511*c2c66affSColin Finck #endif 2512*c2c66affSColin Finck } 2513*c2c66affSColin Finck 2514*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 2515*c2c66affSColin Finck { 2516*c2c66affSColin Finck /* This converts from GA to AG */ 2517*c2c66affSColin Finck if (row_info->bit_depth == 8) 2518*c2c66affSColin Finck { 2519*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2520*c2c66affSColin Finck png_bytep dp = sp; 2521*c2c66affSColin Finck png_byte save; 2522*c2c66affSColin Finck png_uint_32 i; 2523*c2c66affSColin Finck 2524*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2525*c2c66affSColin Finck { 2526*c2c66affSColin Finck save = *(--sp); 2527*c2c66affSColin Finck *(--dp) = *(--sp); 2528*c2c66affSColin Finck *(--dp) = save; 2529*c2c66affSColin Finck } 2530*c2c66affSColin Finck } 2531*c2c66affSColin Finck 2532*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2533*c2c66affSColin Finck /* This converts from GGAA to AAGG */ 2534*c2c66affSColin Finck else 2535*c2c66affSColin Finck { 2536*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2537*c2c66affSColin Finck png_bytep dp = sp; 2538*c2c66affSColin Finck png_byte save[2]; 2539*c2c66affSColin Finck png_uint_32 i; 2540*c2c66affSColin Finck 2541*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2542*c2c66affSColin Finck { 2543*c2c66affSColin Finck save[0] = *(--sp); 2544*c2c66affSColin Finck save[1] = *(--sp); 2545*c2c66affSColin Finck *(--dp) = *(--sp); 2546*c2c66affSColin Finck *(--dp) = *(--sp); 2547*c2c66affSColin Finck *(--dp) = save[0]; 2548*c2c66affSColin Finck *(--dp) = save[1]; 2549*c2c66affSColin Finck } 2550*c2c66affSColin Finck } 2551*c2c66affSColin Finck #endif 2552*c2c66affSColin Finck } 2553*c2c66affSColin Finck } 2554*c2c66affSColin Finck } 2555*c2c66affSColin Finck #endif 2556*c2c66affSColin Finck 2557*c2c66affSColin Finck #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 2558*c2c66affSColin Finck static void 2559*c2c66affSColin Finck png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 2560*c2c66affSColin Finck { 2561*c2c66affSColin Finck png_uint_32 row_width; 2562*c2c66affSColin Finck png_debug(1, "in png_do_read_invert_alpha"); 2563*c2c66affSColin Finck 2564*c2c66affSColin Finck row_width = row_info->width; 2565*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 2566*c2c66affSColin Finck { 2567*c2c66affSColin Finck if (row_info->bit_depth == 8) 2568*c2c66affSColin Finck { 2569*c2c66affSColin Finck /* This inverts the alpha channel in RGBA */ 2570*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2571*c2c66affSColin Finck png_bytep dp = sp; 2572*c2c66affSColin Finck png_uint_32 i; 2573*c2c66affSColin Finck 2574*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2575*c2c66affSColin Finck { 2576*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2577*c2c66affSColin Finck 2578*c2c66affSColin Finck /* This does nothing: 2579*c2c66affSColin Finck *(--dp) = *(--sp); 2580*c2c66affSColin Finck *(--dp) = *(--sp); 2581*c2c66affSColin Finck *(--dp) = *(--sp); 2582*c2c66affSColin Finck We can replace it with: 2583*c2c66affSColin Finck */ 2584*c2c66affSColin Finck sp-=3; 2585*c2c66affSColin Finck dp=sp; 2586*c2c66affSColin Finck } 2587*c2c66affSColin Finck } 2588*c2c66affSColin Finck 2589*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2590*c2c66affSColin Finck /* This inverts the alpha channel in RRGGBBAA */ 2591*c2c66affSColin Finck else 2592*c2c66affSColin Finck { 2593*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2594*c2c66affSColin Finck png_bytep dp = sp; 2595*c2c66affSColin Finck png_uint_32 i; 2596*c2c66affSColin Finck 2597*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2598*c2c66affSColin Finck { 2599*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2600*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2601*c2c66affSColin Finck 2602*c2c66affSColin Finck /* This does nothing: 2603*c2c66affSColin Finck *(--dp) = *(--sp); 2604*c2c66affSColin Finck *(--dp) = *(--sp); 2605*c2c66affSColin Finck *(--dp) = *(--sp); 2606*c2c66affSColin Finck *(--dp) = *(--sp); 2607*c2c66affSColin Finck *(--dp) = *(--sp); 2608*c2c66affSColin Finck *(--dp) = *(--sp); 2609*c2c66affSColin Finck We can replace it with: 2610*c2c66affSColin Finck */ 2611*c2c66affSColin Finck sp-=6; 2612*c2c66affSColin Finck dp=sp; 2613*c2c66affSColin Finck } 2614*c2c66affSColin Finck } 2615*c2c66affSColin Finck #endif 2616*c2c66affSColin Finck } 2617*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 2618*c2c66affSColin Finck { 2619*c2c66affSColin Finck if (row_info->bit_depth == 8) 2620*c2c66affSColin Finck { 2621*c2c66affSColin Finck /* This inverts the alpha channel in GA */ 2622*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2623*c2c66affSColin Finck png_bytep dp = sp; 2624*c2c66affSColin Finck png_uint_32 i; 2625*c2c66affSColin Finck 2626*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2627*c2c66affSColin Finck { 2628*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2629*c2c66affSColin Finck *(--dp) = *(--sp); 2630*c2c66affSColin Finck } 2631*c2c66affSColin Finck } 2632*c2c66affSColin Finck 2633*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2634*c2c66affSColin Finck else 2635*c2c66affSColin Finck { 2636*c2c66affSColin Finck /* This inverts the alpha channel in GGAA */ 2637*c2c66affSColin Finck png_bytep sp = row + row_info->rowbytes; 2638*c2c66affSColin Finck png_bytep dp = sp; 2639*c2c66affSColin Finck png_uint_32 i; 2640*c2c66affSColin Finck 2641*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2642*c2c66affSColin Finck { 2643*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2644*c2c66affSColin Finck *(--dp) = (png_byte)(255 - *(--sp)); 2645*c2c66affSColin Finck /* 2646*c2c66affSColin Finck *(--dp) = *(--sp); 2647*c2c66affSColin Finck *(--dp) = *(--sp); 2648*c2c66affSColin Finck */ 2649*c2c66affSColin Finck sp-=2; 2650*c2c66affSColin Finck dp=sp; 2651*c2c66affSColin Finck } 2652*c2c66affSColin Finck } 2653*c2c66affSColin Finck #endif 2654*c2c66affSColin Finck } 2655*c2c66affSColin Finck } 2656*c2c66affSColin Finck #endif 2657*c2c66affSColin Finck 2658*c2c66affSColin Finck #ifdef PNG_READ_FILLER_SUPPORTED 2659*c2c66affSColin Finck /* Add filler channel if we have RGB color */ 2660*c2c66affSColin Finck static void 2661*c2c66affSColin Finck png_do_read_filler(png_row_infop row_info, png_bytep row, 2662*c2c66affSColin Finck png_uint_32 filler, png_uint_32 flags) 2663*c2c66affSColin Finck { 2664*c2c66affSColin Finck png_uint_32 i; 2665*c2c66affSColin Finck png_uint_32 row_width = row_info->width; 2666*c2c66affSColin Finck 2667*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2668*c2c66affSColin Finck png_byte hi_filler = (png_byte)(filler>>8); 2669*c2c66affSColin Finck #endif 2670*c2c66affSColin Finck png_byte lo_filler = (png_byte)filler; 2671*c2c66affSColin Finck 2672*c2c66affSColin Finck png_debug(1, "in png_do_read_filler"); 2673*c2c66affSColin Finck 2674*c2c66affSColin Finck if ( 2675*c2c66affSColin Finck row_info->color_type == PNG_COLOR_TYPE_GRAY) 2676*c2c66affSColin Finck { 2677*c2c66affSColin Finck if (row_info->bit_depth == 8) 2678*c2c66affSColin Finck { 2679*c2c66affSColin Finck if ((flags & PNG_FLAG_FILLER_AFTER) != 0) 2680*c2c66affSColin Finck { 2681*c2c66affSColin Finck /* This changes the data from G to GX */ 2682*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width; 2683*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width; 2684*c2c66affSColin Finck for (i = 1; i < row_width; i++) 2685*c2c66affSColin Finck { 2686*c2c66affSColin Finck *(--dp) = lo_filler; 2687*c2c66affSColin Finck *(--dp) = *(--sp); 2688*c2c66affSColin Finck } 2689*c2c66affSColin Finck *(--dp) = lo_filler; 2690*c2c66affSColin Finck row_info->channels = 2; 2691*c2c66affSColin Finck row_info->pixel_depth = 16; 2692*c2c66affSColin Finck row_info->rowbytes = row_width * 2; 2693*c2c66affSColin Finck } 2694*c2c66affSColin Finck 2695*c2c66affSColin Finck else 2696*c2c66affSColin Finck { 2697*c2c66affSColin Finck /* This changes the data from G to XG */ 2698*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width; 2699*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width; 2700*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2701*c2c66affSColin Finck { 2702*c2c66affSColin Finck *(--dp) = *(--sp); 2703*c2c66affSColin Finck *(--dp) = lo_filler; 2704*c2c66affSColin Finck } 2705*c2c66affSColin Finck row_info->channels = 2; 2706*c2c66affSColin Finck row_info->pixel_depth = 16; 2707*c2c66affSColin Finck row_info->rowbytes = row_width * 2; 2708*c2c66affSColin Finck } 2709*c2c66affSColin Finck } 2710*c2c66affSColin Finck 2711*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2712*c2c66affSColin Finck else if (row_info->bit_depth == 16) 2713*c2c66affSColin Finck { 2714*c2c66affSColin Finck if ((flags & PNG_FLAG_FILLER_AFTER) != 0) 2715*c2c66affSColin Finck { 2716*c2c66affSColin Finck /* This changes the data from GG to GGXX */ 2717*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 2; 2718*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2719*c2c66affSColin Finck for (i = 1; i < row_width; i++) 2720*c2c66affSColin Finck { 2721*c2c66affSColin Finck *(--dp) = lo_filler; 2722*c2c66affSColin Finck *(--dp) = hi_filler; 2723*c2c66affSColin Finck *(--dp) = *(--sp); 2724*c2c66affSColin Finck *(--dp) = *(--sp); 2725*c2c66affSColin Finck } 2726*c2c66affSColin Finck *(--dp) = lo_filler; 2727*c2c66affSColin Finck *(--dp) = hi_filler; 2728*c2c66affSColin Finck row_info->channels = 2; 2729*c2c66affSColin Finck row_info->pixel_depth = 32; 2730*c2c66affSColin Finck row_info->rowbytes = row_width * 4; 2731*c2c66affSColin Finck } 2732*c2c66affSColin Finck 2733*c2c66affSColin Finck else 2734*c2c66affSColin Finck { 2735*c2c66affSColin Finck /* This changes the data from GG to XXGG */ 2736*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 2; 2737*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2738*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2739*c2c66affSColin Finck { 2740*c2c66affSColin Finck *(--dp) = *(--sp); 2741*c2c66affSColin Finck *(--dp) = *(--sp); 2742*c2c66affSColin Finck *(--dp) = lo_filler; 2743*c2c66affSColin Finck *(--dp) = hi_filler; 2744*c2c66affSColin Finck } 2745*c2c66affSColin Finck row_info->channels = 2; 2746*c2c66affSColin Finck row_info->pixel_depth = 32; 2747*c2c66affSColin Finck row_info->rowbytes = row_width * 4; 2748*c2c66affSColin Finck } 2749*c2c66affSColin Finck } 2750*c2c66affSColin Finck #endif 2751*c2c66affSColin Finck } /* COLOR_TYPE == GRAY */ 2752*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 2753*c2c66affSColin Finck { 2754*c2c66affSColin Finck if (row_info->bit_depth == 8) 2755*c2c66affSColin Finck { 2756*c2c66affSColin Finck if ((flags & PNG_FLAG_FILLER_AFTER) != 0) 2757*c2c66affSColin Finck { 2758*c2c66affSColin Finck /* This changes the data from RGB to RGBX */ 2759*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 3; 2760*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width; 2761*c2c66affSColin Finck for (i = 1; i < row_width; i++) 2762*c2c66affSColin Finck { 2763*c2c66affSColin Finck *(--dp) = lo_filler; 2764*c2c66affSColin Finck *(--dp) = *(--sp); 2765*c2c66affSColin Finck *(--dp) = *(--sp); 2766*c2c66affSColin Finck *(--dp) = *(--sp); 2767*c2c66affSColin Finck } 2768*c2c66affSColin Finck *(--dp) = lo_filler; 2769*c2c66affSColin Finck row_info->channels = 4; 2770*c2c66affSColin Finck row_info->pixel_depth = 32; 2771*c2c66affSColin Finck row_info->rowbytes = row_width * 4; 2772*c2c66affSColin Finck } 2773*c2c66affSColin Finck 2774*c2c66affSColin Finck else 2775*c2c66affSColin Finck { 2776*c2c66affSColin Finck /* This changes the data from RGB to XRGB */ 2777*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 3; 2778*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width; 2779*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2780*c2c66affSColin Finck { 2781*c2c66affSColin Finck *(--dp) = *(--sp); 2782*c2c66affSColin Finck *(--dp) = *(--sp); 2783*c2c66affSColin Finck *(--dp) = *(--sp); 2784*c2c66affSColin Finck *(--dp) = lo_filler; 2785*c2c66affSColin Finck } 2786*c2c66affSColin Finck row_info->channels = 4; 2787*c2c66affSColin Finck row_info->pixel_depth = 32; 2788*c2c66affSColin Finck row_info->rowbytes = row_width * 4; 2789*c2c66affSColin Finck } 2790*c2c66affSColin Finck } 2791*c2c66affSColin Finck 2792*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 2793*c2c66affSColin Finck else if (row_info->bit_depth == 16) 2794*c2c66affSColin Finck { 2795*c2c66affSColin Finck if ((flags & PNG_FLAG_FILLER_AFTER) != 0) 2796*c2c66affSColin Finck { 2797*c2c66affSColin Finck /* This changes the data from RRGGBB to RRGGBBXX */ 2798*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 6; 2799*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2800*c2c66affSColin Finck for (i = 1; i < row_width; i++) 2801*c2c66affSColin Finck { 2802*c2c66affSColin Finck *(--dp) = lo_filler; 2803*c2c66affSColin Finck *(--dp) = hi_filler; 2804*c2c66affSColin Finck *(--dp) = *(--sp); 2805*c2c66affSColin Finck *(--dp) = *(--sp); 2806*c2c66affSColin Finck *(--dp) = *(--sp); 2807*c2c66affSColin Finck *(--dp) = *(--sp); 2808*c2c66affSColin Finck *(--dp) = *(--sp); 2809*c2c66affSColin Finck *(--dp) = *(--sp); 2810*c2c66affSColin Finck } 2811*c2c66affSColin Finck *(--dp) = lo_filler; 2812*c2c66affSColin Finck *(--dp) = hi_filler; 2813*c2c66affSColin Finck row_info->channels = 4; 2814*c2c66affSColin Finck row_info->pixel_depth = 64; 2815*c2c66affSColin Finck row_info->rowbytes = row_width * 8; 2816*c2c66affSColin Finck } 2817*c2c66affSColin Finck 2818*c2c66affSColin Finck else 2819*c2c66affSColin Finck { 2820*c2c66affSColin Finck /* This changes the data from RRGGBB to XXRRGGBB */ 2821*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 6; 2822*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2823*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2824*c2c66affSColin Finck { 2825*c2c66affSColin Finck *(--dp) = *(--sp); 2826*c2c66affSColin Finck *(--dp) = *(--sp); 2827*c2c66affSColin Finck *(--dp) = *(--sp); 2828*c2c66affSColin Finck *(--dp) = *(--sp); 2829*c2c66affSColin Finck *(--dp) = *(--sp); 2830*c2c66affSColin Finck *(--dp) = *(--sp); 2831*c2c66affSColin Finck *(--dp) = lo_filler; 2832*c2c66affSColin Finck *(--dp) = hi_filler; 2833*c2c66affSColin Finck } 2834*c2c66affSColin Finck 2835*c2c66affSColin Finck row_info->channels = 4; 2836*c2c66affSColin Finck row_info->pixel_depth = 64; 2837*c2c66affSColin Finck row_info->rowbytes = row_width * 8; 2838*c2c66affSColin Finck } 2839*c2c66affSColin Finck } 2840*c2c66affSColin Finck #endif 2841*c2c66affSColin Finck } /* COLOR_TYPE == RGB */ 2842*c2c66affSColin Finck } 2843*c2c66affSColin Finck #endif 2844*c2c66affSColin Finck 2845*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 2846*c2c66affSColin Finck /* Expand grayscale files to RGB, with or without alpha */ 2847*c2c66affSColin Finck static void 2848*c2c66affSColin Finck png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 2849*c2c66affSColin Finck { 2850*c2c66affSColin Finck png_uint_32 i; 2851*c2c66affSColin Finck png_uint_32 row_width = row_info->width; 2852*c2c66affSColin Finck 2853*c2c66affSColin Finck png_debug(1, "in png_do_gray_to_rgb"); 2854*c2c66affSColin Finck 2855*c2c66affSColin Finck if (row_info->bit_depth >= 8 && 2856*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0) 2857*c2c66affSColin Finck { 2858*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 2859*c2c66affSColin Finck { 2860*c2c66affSColin Finck if (row_info->bit_depth == 8) 2861*c2c66affSColin Finck { 2862*c2c66affSColin Finck /* This changes G to RGB */ 2863*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width - 1; 2864*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2865*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2866*c2c66affSColin Finck { 2867*c2c66affSColin Finck *(dp--) = *sp; 2868*c2c66affSColin Finck *(dp--) = *sp; 2869*c2c66affSColin Finck *(dp--) = *(sp--); 2870*c2c66affSColin Finck } 2871*c2c66affSColin Finck } 2872*c2c66affSColin Finck 2873*c2c66affSColin Finck else 2874*c2c66affSColin Finck { 2875*c2c66affSColin Finck /* This changes GG to RRGGBB */ 2876*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 2 - 1; 2877*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 4; 2878*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2879*c2c66affSColin Finck { 2880*c2c66affSColin Finck *(dp--) = *sp; 2881*c2c66affSColin Finck *(dp--) = *(sp - 1); 2882*c2c66affSColin Finck *(dp--) = *sp; 2883*c2c66affSColin Finck *(dp--) = *(sp - 1); 2884*c2c66affSColin Finck *(dp--) = *(sp--); 2885*c2c66affSColin Finck *(dp--) = *(sp--); 2886*c2c66affSColin Finck } 2887*c2c66affSColin Finck } 2888*c2c66affSColin Finck } 2889*c2c66affSColin Finck 2890*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 2891*c2c66affSColin Finck { 2892*c2c66affSColin Finck if (row_info->bit_depth == 8) 2893*c2c66affSColin Finck { 2894*c2c66affSColin Finck /* This changes GA to RGBA */ 2895*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 2 - 1; 2896*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 2; 2897*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2898*c2c66affSColin Finck { 2899*c2c66affSColin Finck *(dp--) = *(sp--); 2900*c2c66affSColin Finck *(dp--) = *sp; 2901*c2c66affSColin Finck *(dp--) = *sp; 2902*c2c66affSColin Finck *(dp--) = *(sp--); 2903*c2c66affSColin Finck } 2904*c2c66affSColin Finck } 2905*c2c66affSColin Finck 2906*c2c66affSColin Finck else 2907*c2c66affSColin Finck { 2908*c2c66affSColin Finck /* This changes GGAA to RRGGBBAA */ 2909*c2c66affSColin Finck png_bytep sp = row + (png_size_t)row_width * 4 - 1; 2910*c2c66affSColin Finck png_bytep dp = sp + (png_size_t)row_width * 4; 2911*c2c66affSColin Finck for (i = 0; i < row_width; i++) 2912*c2c66affSColin Finck { 2913*c2c66affSColin Finck *(dp--) = *(sp--); 2914*c2c66affSColin Finck *(dp--) = *(sp--); 2915*c2c66affSColin Finck *(dp--) = *sp; 2916*c2c66affSColin Finck *(dp--) = *(sp - 1); 2917*c2c66affSColin Finck *(dp--) = *sp; 2918*c2c66affSColin Finck *(dp--) = *(sp - 1); 2919*c2c66affSColin Finck *(dp--) = *(sp--); 2920*c2c66affSColin Finck *(dp--) = *(sp--); 2921*c2c66affSColin Finck } 2922*c2c66affSColin Finck } 2923*c2c66affSColin Finck } 2924*c2c66affSColin Finck row_info->channels = (png_byte)(row_info->channels + 2); 2925*c2c66affSColin Finck row_info->color_type |= PNG_COLOR_MASK_COLOR; 2926*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->channels * 2927*c2c66affSColin Finck row_info->bit_depth); 2928*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 2929*c2c66affSColin Finck } 2930*c2c66affSColin Finck } 2931*c2c66affSColin Finck #endif 2932*c2c66affSColin Finck 2933*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2934*c2c66affSColin Finck /* Reduce RGB files to grayscale, with or without alpha 2935*c2c66affSColin Finck * using the equation given in Poynton's ColorFAQ of 1998-01-04 at 2936*c2c66affSColin Finck * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but 2937*c2c66affSColin Finck * versions dated 1998 through November 2002 have been archived at 2938*c2c66affSColin Finck * https://web.archive.org/web/20000816232553/www.inforamp.net/ 2939*c2c66affSColin Finck * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) 2940*c2c66affSColin Finck * Charles Poynton poynton at poynton.com 2941*c2c66affSColin Finck * 2942*c2c66affSColin Finck * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 2943*c2c66affSColin Finck * 2944*c2c66affSColin Finck * which can be expressed with integers as 2945*c2c66affSColin Finck * 2946*c2c66affSColin Finck * Y = (6969 * R + 23434 * G + 2365 * B)/32768 2947*c2c66affSColin Finck * 2948*c2c66affSColin Finck * Poynton's current link (as of January 2003 through July 2011): 2949*c2c66affSColin Finck * <http://www.poynton.com/notes/colour_and_gamma/> 2950*c2c66affSColin Finck * has changed the numbers slightly: 2951*c2c66affSColin Finck * 2952*c2c66affSColin Finck * Y = 0.2126*R + 0.7152*G + 0.0722*B 2953*c2c66affSColin Finck * 2954*c2c66affSColin Finck * which can be expressed with integers as 2955*c2c66affSColin Finck * 2956*c2c66affSColin Finck * Y = (6966 * R + 23436 * G + 2366 * B)/32768 2957*c2c66affSColin Finck * 2958*c2c66affSColin Finck * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 2959*c2c66affSColin Finck * end point chromaticities and the D65 white point. Depending on the 2960*c2c66affSColin Finck * precision used for the D65 white point this produces a variety of different 2961*c2c66affSColin Finck * numbers, however if the four decimal place value used in ITU-R Rec 709 is 2962*c2c66affSColin Finck * used (0.3127,0.3290) the Y calculation would be: 2963*c2c66affSColin Finck * 2964*c2c66affSColin Finck * Y = (6968 * R + 23435 * G + 2366 * B)/32768 2965*c2c66affSColin Finck * 2966*c2c66affSColin Finck * While this is correct the rounding results in an overflow for white, because 2967*c2c66affSColin Finck * the sum of the rounded coefficients is 32769, not 32768. Consequently 2968*c2c66affSColin Finck * libpng uses, instead, the closest non-overflowing approximation: 2969*c2c66affSColin Finck * 2970*c2c66affSColin Finck * Y = (6968 * R + 23434 * G + 2366 * B)/32768 2971*c2c66affSColin Finck * 2972*c2c66affSColin Finck * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk 2973*c2c66affSColin Finck * (including an sRGB chunk) then the chromaticities are used to calculate the 2974*c2c66affSColin Finck * coefficients. See the chunk handling in pngrutil.c for more information. 2975*c2c66affSColin Finck * 2976*c2c66affSColin Finck * In all cases the calculation is to be done in a linear colorspace. If no 2977*c2c66affSColin Finck * gamma information is available to correct the encoding of the original RGB 2978*c2c66affSColin Finck * values this results in an implicit assumption that the original PNG RGB 2979*c2c66affSColin Finck * values were linear. 2980*c2c66affSColin Finck * 2981*c2c66affSColin Finck * Other integer coefficents can be used via png_set_rgb_to_gray(). Because 2982*c2c66affSColin Finck * the API takes just red and green coefficients the blue coefficient is 2983*c2c66affSColin Finck * calculated to make the sum 32768. This will result in different rounding 2984*c2c66affSColin Finck * to that used above. 2985*c2c66affSColin Finck */ 2986*c2c66affSColin Finck static int 2987*c2c66affSColin Finck png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) 2988*c2c66affSColin Finck 2989*c2c66affSColin Finck { 2990*c2c66affSColin Finck int rgb_error = 0; 2991*c2c66affSColin Finck 2992*c2c66affSColin Finck png_debug(1, "in png_do_rgb_to_gray"); 2993*c2c66affSColin Finck 2994*c2c66affSColin Finck if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 && 2995*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) 2996*c2c66affSColin Finck { 2997*c2c66affSColin Finck PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 2998*c2c66affSColin Finck PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 2999*c2c66affSColin Finck PNG_CONST png_uint_32 bc = 32768 - rc - gc; 3000*c2c66affSColin Finck PNG_CONST png_uint_32 row_width = row_info->width; 3001*c2c66affSColin Finck PNG_CONST int have_alpha = 3002*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; 3003*c2c66affSColin Finck 3004*c2c66affSColin Finck if (row_info->bit_depth == 8) 3005*c2c66affSColin Finck { 3006*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3007*c2c66affSColin Finck /* Notice that gamma to/from 1 are not necessarily inverses (if 3008*c2c66affSColin Finck * there is an overall gamma correction). Prior to 1.5.5 this code 3009*c2c66affSColin Finck * checked the linearized values for equality; this doesn't match 3010*c2c66affSColin Finck * the documentation, the original values must be checked. 3011*c2c66affSColin Finck */ 3012*c2c66affSColin Finck if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 3013*c2c66affSColin Finck { 3014*c2c66affSColin Finck png_bytep sp = row; 3015*c2c66affSColin Finck png_bytep dp = row; 3016*c2c66affSColin Finck png_uint_32 i; 3017*c2c66affSColin Finck 3018*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3019*c2c66affSColin Finck { 3020*c2c66affSColin Finck png_byte red = *(sp++); 3021*c2c66affSColin Finck png_byte green = *(sp++); 3022*c2c66affSColin Finck png_byte blue = *(sp++); 3023*c2c66affSColin Finck 3024*c2c66affSColin Finck if (red != green || red != blue) 3025*c2c66affSColin Finck { 3026*c2c66affSColin Finck red = png_ptr->gamma_to_1[red]; 3027*c2c66affSColin Finck green = png_ptr->gamma_to_1[green]; 3028*c2c66affSColin Finck blue = png_ptr->gamma_to_1[blue]; 3029*c2c66affSColin Finck 3030*c2c66affSColin Finck rgb_error |= 1; 3031*c2c66affSColin Finck *(dp++) = png_ptr->gamma_from_1[ 3032*c2c66affSColin Finck (rc*red + gc*green + bc*blue + 16384)>>15]; 3033*c2c66affSColin Finck } 3034*c2c66affSColin Finck 3035*c2c66affSColin Finck else 3036*c2c66affSColin Finck { 3037*c2c66affSColin Finck /* If there is no overall correction the table will not be 3038*c2c66affSColin Finck * set. 3039*c2c66affSColin Finck */ 3040*c2c66affSColin Finck if (png_ptr->gamma_table != NULL) 3041*c2c66affSColin Finck red = png_ptr->gamma_table[red]; 3042*c2c66affSColin Finck 3043*c2c66affSColin Finck *(dp++) = red; 3044*c2c66affSColin Finck } 3045*c2c66affSColin Finck 3046*c2c66affSColin Finck if (have_alpha != 0) 3047*c2c66affSColin Finck *(dp++) = *(sp++); 3048*c2c66affSColin Finck } 3049*c2c66affSColin Finck } 3050*c2c66affSColin Finck else 3051*c2c66affSColin Finck #endif 3052*c2c66affSColin Finck { 3053*c2c66affSColin Finck png_bytep sp = row; 3054*c2c66affSColin Finck png_bytep dp = row; 3055*c2c66affSColin Finck png_uint_32 i; 3056*c2c66affSColin Finck 3057*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3058*c2c66affSColin Finck { 3059*c2c66affSColin Finck png_byte red = *(sp++); 3060*c2c66affSColin Finck png_byte green = *(sp++); 3061*c2c66affSColin Finck png_byte blue = *(sp++); 3062*c2c66affSColin Finck 3063*c2c66affSColin Finck if (red != green || red != blue) 3064*c2c66affSColin Finck { 3065*c2c66affSColin Finck rgb_error |= 1; 3066*c2c66affSColin Finck /* NOTE: this is the historical approach which simply 3067*c2c66affSColin Finck * truncates the results. 3068*c2c66affSColin Finck */ 3069*c2c66affSColin Finck *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 3070*c2c66affSColin Finck } 3071*c2c66affSColin Finck 3072*c2c66affSColin Finck else 3073*c2c66affSColin Finck *(dp++) = red; 3074*c2c66affSColin Finck 3075*c2c66affSColin Finck if (have_alpha != 0) 3076*c2c66affSColin Finck *(dp++) = *(sp++); 3077*c2c66affSColin Finck } 3078*c2c66affSColin Finck } 3079*c2c66affSColin Finck } 3080*c2c66affSColin Finck 3081*c2c66affSColin Finck else /* RGB bit_depth == 16 */ 3082*c2c66affSColin Finck { 3083*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3084*c2c66affSColin Finck if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) 3085*c2c66affSColin Finck { 3086*c2c66affSColin Finck png_bytep sp = row; 3087*c2c66affSColin Finck png_bytep dp = row; 3088*c2c66affSColin Finck png_uint_32 i; 3089*c2c66affSColin Finck 3090*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3091*c2c66affSColin Finck { 3092*c2c66affSColin Finck png_uint_16 red, green, blue, w; 3093*c2c66affSColin Finck png_byte hi,lo; 3094*c2c66affSColin Finck 3095*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo)); 3096*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo)); 3097*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo)); 3098*c2c66affSColin Finck 3099*c2c66affSColin Finck if (red == green && red == blue) 3100*c2c66affSColin Finck { 3101*c2c66affSColin Finck if (png_ptr->gamma_16_table != NULL) 3102*c2c66affSColin Finck w = png_ptr->gamma_16_table[(red & 0xff) 3103*c2c66affSColin Finck >> png_ptr->gamma_shift][red >> 8]; 3104*c2c66affSColin Finck 3105*c2c66affSColin Finck else 3106*c2c66affSColin Finck w = red; 3107*c2c66affSColin Finck } 3108*c2c66affSColin Finck 3109*c2c66affSColin Finck else 3110*c2c66affSColin Finck { 3111*c2c66affSColin Finck png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red & 0xff) 3112*c2c66affSColin Finck >> png_ptr->gamma_shift][red>>8]; 3113*c2c66affSColin Finck png_uint_16 green_1 = 3114*c2c66affSColin Finck png_ptr->gamma_16_to_1[(green & 0xff) >> 3115*c2c66affSColin Finck png_ptr->gamma_shift][green>>8]; 3116*c2c66affSColin Finck png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue & 0xff) 3117*c2c66affSColin Finck >> png_ptr->gamma_shift][blue>>8]; 3118*c2c66affSColin Finck png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 3119*c2c66affSColin Finck + bc*blue_1 + 16384)>>15); 3120*c2c66affSColin Finck w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >> 3121*c2c66affSColin Finck png_ptr->gamma_shift][gray16 >> 8]; 3122*c2c66affSColin Finck rgb_error |= 1; 3123*c2c66affSColin Finck } 3124*c2c66affSColin Finck 3125*c2c66affSColin Finck *(dp++) = (png_byte)((w>>8) & 0xff); 3126*c2c66affSColin Finck *(dp++) = (png_byte)(w & 0xff); 3127*c2c66affSColin Finck 3128*c2c66affSColin Finck if (have_alpha != 0) 3129*c2c66affSColin Finck { 3130*c2c66affSColin Finck *(dp++) = *(sp++); 3131*c2c66affSColin Finck *(dp++) = *(sp++); 3132*c2c66affSColin Finck } 3133*c2c66affSColin Finck } 3134*c2c66affSColin Finck } 3135*c2c66affSColin Finck else 3136*c2c66affSColin Finck #endif 3137*c2c66affSColin Finck { 3138*c2c66affSColin Finck png_bytep sp = row; 3139*c2c66affSColin Finck png_bytep dp = row; 3140*c2c66affSColin Finck png_uint_32 i; 3141*c2c66affSColin Finck 3142*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3143*c2c66affSColin Finck { 3144*c2c66affSColin Finck png_uint_16 red, green, blue, gray16; 3145*c2c66affSColin Finck png_byte hi,lo; 3146*c2c66affSColin Finck 3147*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo)); 3148*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo)); 3149*c2c66affSColin Finck hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo)); 3150*c2c66affSColin Finck 3151*c2c66affSColin Finck if (red != green || red != blue) 3152*c2c66affSColin Finck rgb_error |= 1; 3153*c2c66affSColin Finck 3154*c2c66affSColin Finck /* From 1.5.5 in the 16-bit case do the accurate conversion even 3155*c2c66affSColin Finck * in the 'fast' case - this is because this is where the code 3156*c2c66affSColin Finck * ends up when handling linear 16-bit data. 3157*c2c66affSColin Finck */ 3158*c2c66affSColin Finck gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> 3159*c2c66affSColin Finck 15); 3160*c2c66affSColin Finck *(dp++) = (png_byte)((gray16 >> 8) & 0xff); 3161*c2c66affSColin Finck *(dp++) = (png_byte)(gray16 & 0xff); 3162*c2c66affSColin Finck 3163*c2c66affSColin Finck if (have_alpha != 0) 3164*c2c66affSColin Finck { 3165*c2c66affSColin Finck *(dp++) = *(sp++); 3166*c2c66affSColin Finck *(dp++) = *(sp++); 3167*c2c66affSColin Finck } 3168*c2c66affSColin Finck } 3169*c2c66affSColin Finck } 3170*c2c66affSColin Finck } 3171*c2c66affSColin Finck 3172*c2c66affSColin Finck row_info->channels = (png_byte)(row_info->channels - 2); 3173*c2c66affSColin Finck row_info->color_type = (png_byte)(row_info->color_type & 3174*c2c66affSColin Finck ~PNG_COLOR_MASK_COLOR); 3175*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->channels * 3176*c2c66affSColin Finck row_info->bit_depth); 3177*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 3178*c2c66affSColin Finck } 3179*c2c66affSColin Finck return rgb_error; 3180*c2c66affSColin Finck } 3181*c2c66affSColin Finck #endif 3182*c2c66affSColin Finck 3183*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 3184*c2c66affSColin Finck defined(PNG_READ_ALPHA_MODE_SUPPORTED) 3185*c2c66affSColin Finck /* Replace any alpha or transparency with the supplied background color. 3186*c2c66affSColin Finck * "background" is already in the screen gamma, while "background_1" is 3187*c2c66affSColin Finck * at a gamma of 1.0. Paletted files have already been taken care of. 3188*c2c66affSColin Finck */ 3189*c2c66affSColin Finck static void 3190*c2c66affSColin Finck png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 3191*c2c66affSColin Finck { 3192*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3193*c2c66affSColin Finck png_const_bytep gamma_table = png_ptr->gamma_table; 3194*c2c66affSColin Finck png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; 3195*c2c66affSColin Finck png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; 3196*c2c66affSColin Finck png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; 3197*c2c66affSColin Finck png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; 3198*c2c66affSColin Finck png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; 3199*c2c66affSColin Finck int gamma_shift = png_ptr->gamma_shift; 3200*c2c66affSColin Finck int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; 3201*c2c66affSColin Finck #endif 3202*c2c66affSColin Finck 3203*c2c66affSColin Finck png_bytep sp; 3204*c2c66affSColin Finck png_uint_32 i; 3205*c2c66affSColin Finck png_uint_32 row_width = row_info->width; 3206*c2c66affSColin Finck int shift; 3207*c2c66affSColin Finck 3208*c2c66affSColin Finck png_debug(1, "in png_do_compose"); 3209*c2c66affSColin Finck 3210*c2c66affSColin Finck { 3211*c2c66affSColin Finck switch (row_info->color_type) 3212*c2c66affSColin Finck { 3213*c2c66affSColin Finck case PNG_COLOR_TYPE_GRAY: 3214*c2c66affSColin Finck { 3215*c2c66affSColin Finck switch (row_info->bit_depth) 3216*c2c66affSColin Finck { 3217*c2c66affSColin Finck case 1: 3218*c2c66affSColin Finck { 3219*c2c66affSColin Finck sp = row; 3220*c2c66affSColin Finck shift = 7; 3221*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3222*c2c66affSColin Finck { 3223*c2c66affSColin Finck if ((png_uint_16)((*sp >> shift) & 0x01) 3224*c2c66affSColin Finck == png_ptr->trans_color.gray) 3225*c2c66affSColin Finck { 3226*c2c66affSColin Finck unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); 3227*c2c66affSColin Finck tmp |= 3228*c2c66affSColin Finck (unsigned int)(png_ptr->background.gray << shift); 3229*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3230*c2c66affSColin Finck } 3231*c2c66affSColin Finck 3232*c2c66affSColin Finck if (shift == 0) 3233*c2c66affSColin Finck { 3234*c2c66affSColin Finck shift = 7; 3235*c2c66affSColin Finck sp++; 3236*c2c66affSColin Finck } 3237*c2c66affSColin Finck 3238*c2c66affSColin Finck else 3239*c2c66affSColin Finck shift--; 3240*c2c66affSColin Finck } 3241*c2c66affSColin Finck break; 3242*c2c66affSColin Finck } 3243*c2c66affSColin Finck 3244*c2c66affSColin Finck case 2: 3245*c2c66affSColin Finck { 3246*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3247*c2c66affSColin Finck if (gamma_table != NULL) 3248*c2c66affSColin Finck { 3249*c2c66affSColin Finck sp = row; 3250*c2c66affSColin Finck shift = 6; 3251*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3252*c2c66affSColin Finck { 3253*c2c66affSColin Finck if ((png_uint_16)((*sp >> shift) & 0x03) 3254*c2c66affSColin Finck == png_ptr->trans_color.gray) 3255*c2c66affSColin Finck { 3256*c2c66affSColin Finck unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 3257*c2c66affSColin Finck tmp |= 3258*c2c66affSColin Finck (unsigned int)png_ptr->background.gray << shift; 3259*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3260*c2c66affSColin Finck } 3261*c2c66affSColin Finck 3262*c2c66affSColin Finck else 3263*c2c66affSColin Finck { 3264*c2c66affSColin Finck unsigned int p = (*sp >> shift) & 0x03; 3265*c2c66affSColin Finck unsigned int g = (gamma_table [p | (p << 2) | 3266*c2c66affSColin Finck (p << 4) | (p << 6)] >> 6) & 0x03; 3267*c2c66affSColin Finck unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 3268*c2c66affSColin Finck tmp |= (unsigned int)(g << shift); 3269*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3270*c2c66affSColin Finck } 3271*c2c66affSColin Finck 3272*c2c66affSColin Finck if (shift == 0) 3273*c2c66affSColin Finck { 3274*c2c66affSColin Finck shift = 6; 3275*c2c66affSColin Finck sp++; 3276*c2c66affSColin Finck } 3277*c2c66affSColin Finck 3278*c2c66affSColin Finck else 3279*c2c66affSColin Finck shift -= 2; 3280*c2c66affSColin Finck } 3281*c2c66affSColin Finck } 3282*c2c66affSColin Finck 3283*c2c66affSColin Finck else 3284*c2c66affSColin Finck #endif 3285*c2c66affSColin Finck { 3286*c2c66affSColin Finck sp = row; 3287*c2c66affSColin Finck shift = 6; 3288*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3289*c2c66affSColin Finck { 3290*c2c66affSColin Finck if ((png_uint_16)((*sp >> shift) & 0x03) 3291*c2c66affSColin Finck == png_ptr->trans_color.gray) 3292*c2c66affSColin Finck { 3293*c2c66affSColin Finck unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); 3294*c2c66affSColin Finck tmp |= 3295*c2c66affSColin Finck (unsigned int)png_ptr->background.gray << shift; 3296*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3297*c2c66affSColin Finck } 3298*c2c66affSColin Finck 3299*c2c66affSColin Finck if (shift == 0) 3300*c2c66affSColin Finck { 3301*c2c66affSColin Finck shift = 6; 3302*c2c66affSColin Finck sp++; 3303*c2c66affSColin Finck } 3304*c2c66affSColin Finck 3305*c2c66affSColin Finck else 3306*c2c66affSColin Finck shift -= 2; 3307*c2c66affSColin Finck } 3308*c2c66affSColin Finck } 3309*c2c66affSColin Finck break; 3310*c2c66affSColin Finck } 3311*c2c66affSColin Finck 3312*c2c66affSColin Finck case 4: 3313*c2c66affSColin Finck { 3314*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3315*c2c66affSColin Finck if (gamma_table != NULL) 3316*c2c66affSColin Finck { 3317*c2c66affSColin Finck sp = row; 3318*c2c66affSColin Finck shift = 4; 3319*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3320*c2c66affSColin Finck { 3321*c2c66affSColin Finck if ((png_uint_16)((*sp >> shift) & 0x0f) 3322*c2c66affSColin Finck == png_ptr->trans_color.gray) 3323*c2c66affSColin Finck { 3324*c2c66affSColin Finck unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); 3325*c2c66affSColin Finck tmp |= 3326*c2c66affSColin Finck (unsigned int)(png_ptr->background.gray << shift); 3327*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3328*c2c66affSColin Finck } 3329*c2c66affSColin Finck 3330*c2c66affSColin Finck else 3331*c2c66affSColin Finck { 3332*c2c66affSColin Finck unsigned int p = (*sp >> shift) & 0x0f; 3333*c2c66affSColin Finck unsigned int g = (gamma_table[p | (p << 4)] >> 4) & 3334*c2c66affSColin Finck 0x0f; 3335*c2c66affSColin Finck unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); 3336*c2c66affSColin Finck tmp |= (unsigned int)(g << shift); 3337*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3338*c2c66affSColin Finck } 3339*c2c66affSColin Finck 3340*c2c66affSColin Finck if (shift == 0) 3341*c2c66affSColin Finck { 3342*c2c66affSColin Finck shift = 4; 3343*c2c66affSColin Finck sp++; 3344*c2c66affSColin Finck } 3345*c2c66affSColin Finck 3346*c2c66affSColin Finck else 3347*c2c66affSColin Finck shift -= 4; 3348*c2c66affSColin Finck } 3349*c2c66affSColin Finck } 3350*c2c66affSColin Finck 3351*c2c66affSColin Finck else 3352*c2c66affSColin Finck #endif 3353*c2c66affSColin Finck { 3354*c2c66affSColin Finck sp = row; 3355*c2c66affSColin Finck shift = 4; 3356*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3357*c2c66affSColin Finck { 3358*c2c66affSColin Finck if ((png_uint_16)((*sp >> shift) & 0x0f) 3359*c2c66affSColin Finck == png_ptr->trans_color.gray) 3360*c2c66affSColin Finck { 3361*c2c66affSColin Finck unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); 3362*c2c66affSColin Finck tmp |= 3363*c2c66affSColin Finck (unsigned int)(png_ptr->background.gray << shift); 3364*c2c66affSColin Finck *sp = (png_byte)(tmp & 0xff); 3365*c2c66affSColin Finck } 3366*c2c66affSColin Finck 3367*c2c66affSColin Finck if (shift == 0) 3368*c2c66affSColin Finck { 3369*c2c66affSColin Finck shift = 4; 3370*c2c66affSColin Finck sp++; 3371*c2c66affSColin Finck } 3372*c2c66affSColin Finck 3373*c2c66affSColin Finck else 3374*c2c66affSColin Finck shift -= 4; 3375*c2c66affSColin Finck } 3376*c2c66affSColin Finck } 3377*c2c66affSColin Finck break; 3378*c2c66affSColin Finck } 3379*c2c66affSColin Finck 3380*c2c66affSColin Finck case 8: 3381*c2c66affSColin Finck { 3382*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3383*c2c66affSColin Finck if (gamma_table != NULL) 3384*c2c66affSColin Finck { 3385*c2c66affSColin Finck sp = row; 3386*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp++) 3387*c2c66affSColin Finck { 3388*c2c66affSColin Finck if (*sp == png_ptr->trans_color.gray) 3389*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.gray; 3390*c2c66affSColin Finck 3391*c2c66affSColin Finck else 3392*c2c66affSColin Finck *sp = gamma_table[*sp]; 3393*c2c66affSColin Finck } 3394*c2c66affSColin Finck } 3395*c2c66affSColin Finck else 3396*c2c66affSColin Finck #endif 3397*c2c66affSColin Finck { 3398*c2c66affSColin Finck sp = row; 3399*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp++) 3400*c2c66affSColin Finck { 3401*c2c66affSColin Finck if (*sp == png_ptr->trans_color.gray) 3402*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.gray; 3403*c2c66affSColin Finck } 3404*c2c66affSColin Finck } 3405*c2c66affSColin Finck break; 3406*c2c66affSColin Finck } 3407*c2c66affSColin Finck 3408*c2c66affSColin Finck case 16: 3409*c2c66affSColin Finck { 3410*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3411*c2c66affSColin Finck if (gamma_16 != NULL) 3412*c2c66affSColin Finck { 3413*c2c66affSColin Finck sp = row; 3414*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 2) 3415*c2c66affSColin Finck { 3416*c2c66affSColin Finck png_uint_16 v; 3417*c2c66affSColin Finck 3418*c2c66affSColin Finck v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3419*c2c66affSColin Finck 3420*c2c66affSColin Finck if (v == png_ptr->trans_color.gray) 3421*c2c66affSColin Finck { 3422*c2c66affSColin Finck /* Background is already in screen gamma */ 3423*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.gray >> 8) 3424*c2c66affSColin Finck & 0xff); 3425*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.gray 3426*c2c66affSColin Finck & 0xff); 3427*c2c66affSColin Finck } 3428*c2c66affSColin Finck 3429*c2c66affSColin Finck else 3430*c2c66affSColin Finck { 3431*c2c66affSColin Finck v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3432*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3433*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3434*c2c66affSColin Finck } 3435*c2c66affSColin Finck } 3436*c2c66affSColin Finck } 3437*c2c66affSColin Finck else 3438*c2c66affSColin Finck #endif 3439*c2c66affSColin Finck { 3440*c2c66affSColin Finck sp = row; 3441*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 2) 3442*c2c66affSColin Finck { 3443*c2c66affSColin Finck png_uint_16 v; 3444*c2c66affSColin Finck 3445*c2c66affSColin Finck v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3446*c2c66affSColin Finck 3447*c2c66affSColin Finck if (v == png_ptr->trans_color.gray) 3448*c2c66affSColin Finck { 3449*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.gray >> 8) 3450*c2c66affSColin Finck & 0xff); 3451*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.gray 3452*c2c66affSColin Finck & 0xff); 3453*c2c66affSColin Finck } 3454*c2c66affSColin Finck } 3455*c2c66affSColin Finck } 3456*c2c66affSColin Finck break; 3457*c2c66affSColin Finck } 3458*c2c66affSColin Finck 3459*c2c66affSColin Finck default: 3460*c2c66affSColin Finck break; 3461*c2c66affSColin Finck } 3462*c2c66affSColin Finck break; 3463*c2c66affSColin Finck } 3464*c2c66affSColin Finck 3465*c2c66affSColin Finck case PNG_COLOR_TYPE_RGB: 3466*c2c66affSColin Finck { 3467*c2c66affSColin Finck if (row_info->bit_depth == 8) 3468*c2c66affSColin Finck { 3469*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3470*c2c66affSColin Finck if (gamma_table != NULL) 3471*c2c66affSColin Finck { 3472*c2c66affSColin Finck sp = row; 3473*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 3) 3474*c2c66affSColin Finck { 3475*c2c66affSColin Finck if (*sp == png_ptr->trans_color.red && 3476*c2c66affSColin Finck *(sp + 1) == png_ptr->trans_color.green && 3477*c2c66affSColin Finck *(sp + 2) == png_ptr->trans_color.blue) 3478*c2c66affSColin Finck { 3479*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.red; 3480*c2c66affSColin Finck *(sp + 1) = (png_byte)png_ptr->background.green; 3481*c2c66affSColin Finck *(sp + 2) = (png_byte)png_ptr->background.blue; 3482*c2c66affSColin Finck } 3483*c2c66affSColin Finck 3484*c2c66affSColin Finck else 3485*c2c66affSColin Finck { 3486*c2c66affSColin Finck *sp = gamma_table[*sp]; 3487*c2c66affSColin Finck *(sp + 1) = gamma_table[*(sp + 1)]; 3488*c2c66affSColin Finck *(sp + 2) = gamma_table[*(sp + 2)]; 3489*c2c66affSColin Finck } 3490*c2c66affSColin Finck } 3491*c2c66affSColin Finck } 3492*c2c66affSColin Finck else 3493*c2c66affSColin Finck #endif 3494*c2c66affSColin Finck { 3495*c2c66affSColin Finck sp = row; 3496*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 3) 3497*c2c66affSColin Finck { 3498*c2c66affSColin Finck if (*sp == png_ptr->trans_color.red && 3499*c2c66affSColin Finck *(sp + 1) == png_ptr->trans_color.green && 3500*c2c66affSColin Finck *(sp + 2) == png_ptr->trans_color.blue) 3501*c2c66affSColin Finck { 3502*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.red; 3503*c2c66affSColin Finck *(sp + 1) = (png_byte)png_ptr->background.green; 3504*c2c66affSColin Finck *(sp + 2) = (png_byte)png_ptr->background.blue; 3505*c2c66affSColin Finck } 3506*c2c66affSColin Finck } 3507*c2c66affSColin Finck } 3508*c2c66affSColin Finck } 3509*c2c66affSColin Finck else /* if (row_info->bit_depth == 16) */ 3510*c2c66affSColin Finck { 3511*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3512*c2c66affSColin Finck if (gamma_16 != NULL) 3513*c2c66affSColin Finck { 3514*c2c66affSColin Finck sp = row; 3515*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 6) 3516*c2c66affSColin Finck { 3517*c2c66affSColin Finck png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3518*c2c66affSColin Finck 3519*c2c66affSColin Finck png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 3520*c2c66affSColin Finck + *(sp + 3)); 3521*c2c66affSColin Finck 3522*c2c66affSColin Finck png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 3523*c2c66affSColin Finck + *(sp + 5)); 3524*c2c66affSColin Finck 3525*c2c66affSColin Finck if (r == png_ptr->trans_color.red && 3526*c2c66affSColin Finck g == png_ptr->trans_color.green && 3527*c2c66affSColin Finck b == png_ptr->trans_color.blue) 3528*c2c66affSColin Finck { 3529*c2c66affSColin Finck /* Background is already in screen gamma */ 3530*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 3531*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 3532*c2c66affSColin Finck *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 3533*c2c66affSColin Finck & 0xff); 3534*c2c66affSColin Finck *(sp + 3) = (png_byte)(png_ptr->background.green 3535*c2c66affSColin Finck & 0xff); 3536*c2c66affSColin Finck *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 3537*c2c66affSColin Finck & 0xff); 3538*c2c66affSColin Finck *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 3539*c2c66affSColin Finck } 3540*c2c66affSColin Finck 3541*c2c66affSColin Finck else 3542*c2c66affSColin Finck { 3543*c2c66affSColin Finck png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3544*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3545*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3546*c2c66affSColin Finck 3547*c2c66affSColin Finck v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3548*c2c66affSColin Finck *(sp + 2) = (png_byte)((v >> 8) & 0xff); 3549*c2c66affSColin Finck *(sp + 3) = (png_byte)(v & 0xff); 3550*c2c66affSColin Finck 3551*c2c66affSColin Finck v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3552*c2c66affSColin Finck *(sp + 4) = (png_byte)((v >> 8) & 0xff); 3553*c2c66affSColin Finck *(sp + 5) = (png_byte)(v & 0xff); 3554*c2c66affSColin Finck } 3555*c2c66affSColin Finck } 3556*c2c66affSColin Finck } 3557*c2c66affSColin Finck 3558*c2c66affSColin Finck else 3559*c2c66affSColin Finck #endif 3560*c2c66affSColin Finck { 3561*c2c66affSColin Finck sp = row; 3562*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 6) 3563*c2c66affSColin Finck { 3564*c2c66affSColin Finck png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3565*c2c66affSColin Finck 3566*c2c66affSColin Finck png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 3567*c2c66affSColin Finck + *(sp + 3)); 3568*c2c66affSColin Finck 3569*c2c66affSColin Finck png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 3570*c2c66affSColin Finck + *(sp + 5)); 3571*c2c66affSColin Finck 3572*c2c66affSColin Finck if (r == png_ptr->trans_color.red && 3573*c2c66affSColin Finck g == png_ptr->trans_color.green && 3574*c2c66affSColin Finck b == png_ptr->trans_color.blue) 3575*c2c66affSColin Finck { 3576*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 3577*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 3578*c2c66affSColin Finck *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 3579*c2c66affSColin Finck & 0xff); 3580*c2c66affSColin Finck *(sp + 3) = (png_byte)(png_ptr->background.green 3581*c2c66affSColin Finck & 0xff); 3582*c2c66affSColin Finck *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 3583*c2c66affSColin Finck & 0xff); 3584*c2c66affSColin Finck *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 3585*c2c66affSColin Finck } 3586*c2c66affSColin Finck } 3587*c2c66affSColin Finck } 3588*c2c66affSColin Finck } 3589*c2c66affSColin Finck break; 3590*c2c66affSColin Finck } 3591*c2c66affSColin Finck 3592*c2c66affSColin Finck case PNG_COLOR_TYPE_GRAY_ALPHA: 3593*c2c66affSColin Finck { 3594*c2c66affSColin Finck if (row_info->bit_depth == 8) 3595*c2c66affSColin Finck { 3596*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3597*c2c66affSColin Finck if (gamma_to_1 != NULL && gamma_from_1 != NULL && 3598*c2c66affSColin Finck gamma_table != NULL) 3599*c2c66affSColin Finck { 3600*c2c66affSColin Finck sp = row; 3601*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 2) 3602*c2c66affSColin Finck { 3603*c2c66affSColin Finck png_uint_16 a = *(sp + 1); 3604*c2c66affSColin Finck 3605*c2c66affSColin Finck if (a == 0xff) 3606*c2c66affSColin Finck *sp = gamma_table[*sp]; 3607*c2c66affSColin Finck 3608*c2c66affSColin Finck else if (a == 0) 3609*c2c66affSColin Finck { 3610*c2c66affSColin Finck /* Background is already in screen gamma */ 3611*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.gray; 3612*c2c66affSColin Finck } 3613*c2c66affSColin Finck 3614*c2c66affSColin Finck else 3615*c2c66affSColin Finck { 3616*c2c66affSColin Finck png_byte v, w; 3617*c2c66affSColin Finck 3618*c2c66affSColin Finck v = gamma_to_1[*sp]; 3619*c2c66affSColin Finck png_composite(w, v, a, png_ptr->background_1.gray); 3620*c2c66affSColin Finck if (optimize == 0) 3621*c2c66affSColin Finck w = gamma_from_1[w]; 3622*c2c66affSColin Finck *sp = w; 3623*c2c66affSColin Finck } 3624*c2c66affSColin Finck } 3625*c2c66affSColin Finck } 3626*c2c66affSColin Finck else 3627*c2c66affSColin Finck #endif 3628*c2c66affSColin Finck { 3629*c2c66affSColin Finck sp = row; 3630*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 2) 3631*c2c66affSColin Finck { 3632*c2c66affSColin Finck png_byte a = *(sp + 1); 3633*c2c66affSColin Finck 3634*c2c66affSColin Finck if (a == 0) 3635*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.gray; 3636*c2c66affSColin Finck 3637*c2c66affSColin Finck else if (a < 0xff) 3638*c2c66affSColin Finck png_composite(*sp, *sp, a, png_ptr->background.gray); 3639*c2c66affSColin Finck } 3640*c2c66affSColin Finck } 3641*c2c66affSColin Finck } 3642*c2c66affSColin Finck else /* if (png_ptr->bit_depth == 16) */ 3643*c2c66affSColin Finck { 3644*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3645*c2c66affSColin Finck if (gamma_16 != NULL && gamma_16_from_1 != NULL && 3646*c2c66affSColin Finck gamma_16_to_1 != NULL) 3647*c2c66affSColin Finck { 3648*c2c66affSColin Finck sp = row; 3649*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 4) 3650*c2c66affSColin Finck { 3651*c2c66affSColin Finck png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 3652*c2c66affSColin Finck + *(sp + 3)); 3653*c2c66affSColin Finck 3654*c2c66affSColin Finck if (a == (png_uint_16)0xffff) 3655*c2c66affSColin Finck { 3656*c2c66affSColin Finck png_uint_16 v; 3657*c2c66affSColin Finck 3658*c2c66affSColin Finck v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3659*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3660*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3661*c2c66affSColin Finck } 3662*c2c66affSColin Finck 3663*c2c66affSColin Finck else if (a == 0) 3664*c2c66affSColin Finck { 3665*c2c66affSColin Finck /* Background is already in screen gamma */ 3666*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.gray >> 8) 3667*c2c66affSColin Finck & 0xff); 3668*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 3669*c2c66affSColin Finck } 3670*c2c66affSColin Finck 3671*c2c66affSColin Finck else 3672*c2c66affSColin Finck { 3673*c2c66affSColin Finck png_uint_16 g, v, w; 3674*c2c66affSColin Finck 3675*c2c66affSColin Finck g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 3676*c2c66affSColin Finck png_composite_16(v, g, a, png_ptr->background_1.gray); 3677*c2c66affSColin Finck if (optimize != 0) 3678*c2c66affSColin Finck w = v; 3679*c2c66affSColin Finck else 3680*c2c66affSColin Finck w = gamma_16_from_1[(v & 0xff) >> 3681*c2c66affSColin Finck gamma_shift][v >> 8]; 3682*c2c66affSColin Finck *sp = (png_byte)((w >> 8) & 0xff); 3683*c2c66affSColin Finck *(sp + 1) = (png_byte)(w & 0xff); 3684*c2c66affSColin Finck } 3685*c2c66affSColin Finck } 3686*c2c66affSColin Finck } 3687*c2c66affSColin Finck else 3688*c2c66affSColin Finck #endif 3689*c2c66affSColin Finck { 3690*c2c66affSColin Finck sp = row; 3691*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 4) 3692*c2c66affSColin Finck { 3693*c2c66affSColin Finck png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 3694*c2c66affSColin Finck + *(sp + 3)); 3695*c2c66affSColin Finck 3696*c2c66affSColin Finck if (a == 0) 3697*c2c66affSColin Finck { 3698*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.gray >> 8) 3699*c2c66affSColin Finck & 0xff); 3700*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 3701*c2c66affSColin Finck } 3702*c2c66affSColin Finck 3703*c2c66affSColin Finck else if (a < 0xffff) 3704*c2c66affSColin Finck { 3705*c2c66affSColin Finck png_uint_16 g, v; 3706*c2c66affSColin Finck 3707*c2c66affSColin Finck g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3708*c2c66affSColin Finck png_composite_16(v, g, a, png_ptr->background.gray); 3709*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3710*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3711*c2c66affSColin Finck } 3712*c2c66affSColin Finck } 3713*c2c66affSColin Finck } 3714*c2c66affSColin Finck } 3715*c2c66affSColin Finck break; 3716*c2c66affSColin Finck } 3717*c2c66affSColin Finck 3718*c2c66affSColin Finck case PNG_COLOR_TYPE_RGB_ALPHA: 3719*c2c66affSColin Finck { 3720*c2c66affSColin Finck if (row_info->bit_depth == 8) 3721*c2c66affSColin Finck { 3722*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3723*c2c66affSColin Finck if (gamma_to_1 != NULL && gamma_from_1 != NULL && 3724*c2c66affSColin Finck gamma_table != NULL) 3725*c2c66affSColin Finck { 3726*c2c66affSColin Finck sp = row; 3727*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 4) 3728*c2c66affSColin Finck { 3729*c2c66affSColin Finck png_byte a = *(sp + 3); 3730*c2c66affSColin Finck 3731*c2c66affSColin Finck if (a == 0xff) 3732*c2c66affSColin Finck { 3733*c2c66affSColin Finck *sp = gamma_table[*sp]; 3734*c2c66affSColin Finck *(sp + 1) = gamma_table[*(sp + 1)]; 3735*c2c66affSColin Finck *(sp + 2) = gamma_table[*(sp + 2)]; 3736*c2c66affSColin Finck } 3737*c2c66affSColin Finck 3738*c2c66affSColin Finck else if (a == 0) 3739*c2c66affSColin Finck { 3740*c2c66affSColin Finck /* Background is already in screen gamma */ 3741*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.red; 3742*c2c66affSColin Finck *(sp + 1) = (png_byte)png_ptr->background.green; 3743*c2c66affSColin Finck *(sp + 2) = (png_byte)png_ptr->background.blue; 3744*c2c66affSColin Finck } 3745*c2c66affSColin Finck 3746*c2c66affSColin Finck else 3747*c2c66affSColin Finck { 3748*c2c66affSColin Finck png_byte v, w; 3749*c2c66affSColin Finck 3750*c2c66affSColin Finck v = gamma_to_1[*sp]; 3751*c2c66affSColin Finck png_composite(w, v, a, png_ptr->background_1.red); 3752*c2c66affSColin Finck if (optimize == 0) w = gamma_from_1[w]; 3753*c2c66affSColin Finck *sp = w; 3754*c2c66affSColin Finck 3755*c2c66affSColin Finck v = gamma_to_1[*(sp + 1)]; 3756*c2c66affSColin Finck png_composite(w, v, a, png_ptr->background_1.green); 3757*c2c66affSColin Finck if (optimize == 0) w = gamma_from_1[w]; 3758*c2c66affSColin Finck *(sp + 1) = w; 3759*c2c66affSColin Finck 3760*c2c66affSColin Finck v = gamma_to_1[*(sp + 2)]; 3761*c2c66affSColin Finck png_composite(w, v, a, png_ptr->background_1.blue); 3762*c2c66affSColin Finck if (optimize == 0) w = gamma_from_1[w]; 3763*c2c66affSColin Finck *(sp + 2) = w; 3764*c2c66affSColin Finck } 3765*c2c66affSColin Finck } 3766*c2c66affSColin Finck } 3767*c2c66affSColin Finck else 3768*c2c66affSColin Finck #endif 3769*c2c66affSColin Finck { 3770*c2c66affSColin Finck sp = row; 3771*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 4) 3772*c2c66affSColin Finck { 3773*c2c66affSColin Finck png_byte a = *(sp + 3); 3774*c2c66affSColin Finck 3775*c2c66affSColin Finck if (a == 0) 3776*c2c66affSColin Finck { 3777*c2c66affSColin Finck *sp = (png_byte)png_ptr->background.red; 3778*c2c66affSColin Finck *(sp + 1) = (png_byte)png_ptr->background.green; 3779*c2c66affSColin Finck *(sp + 2) = (png_byte)png_ptr->background.blue; 3780*c2c66affSColin Finck } 3781*c2c66affSColin Finck 3782*c2c66affSColin Finck else if (a < 0xff) 3783*c2c66affSColin Finck { 3784*c2c66affSColin Finck png_composite(*sp, *sp, a, png_ptr->background.red); 3785*c2c66affSColin Finck 3786*c2c66affSColin Finck png_composite(*(sp + 1), *(sp + 1), a, 3787*c2c66affSColin Finck png_ptr->background.green); 3788*c2c66affSColin Finck 3789*c2c66affSColin Finck png_composite(*(sp + 2), *(sp + 2), a, 3790*c2c66affSColin Finck png_ptr->background.blue); 3791*c2c66affSColin Finck } 3792*c2c66affSColin Finck } 3793*c2c66affSColin Finck } 3794*c2c66affSColin Finck } 3795*c2c66affSColin Finck else /* if (row_info->bit_depth == 16) */ 3796*c2c66affSColin Finck { 3797*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3798*c2c66affSColin Finck if (gamma_16 != NULL && gamma_16_from_1 != NULL && 3799*c2c66affSColin Finck gamma_16_to_1 != NULL) 3800*c2c66affSColin Finck { 3801*c2c66affSColin Finck sp = row; 3802*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 8) 3803*c2c66affSColin Finck { 3804*c2c66affSColin Finck png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 3805*c2c66affSColin Finck << 8) + (png_uint_16)(*(sp + 7))); 3806*c2c66affSColin Finck 3807*c2c66affSColin Finck if (a == (png_uint_16)0xffff) 3808*c2c66affSColin Finck { 3809*c2c66affSColin Finck png_uint_16 v; 3810*c2c66affSColin Finck 3811*c2c66affSColin Finck v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3812*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3813*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3814*c2c66affSColin Finck 3815*c2c66affSColin Finck v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3816*c2c66affSColin Finck *(sp + 2) = (png_byte)((v >> 8) & 0xff); 3817*c2c66affSColin Finck *(sp + 3) = (png_byte)(v & 0xff); 3818*c2c66affSColin Finck 3819*c2c66affSColin Finck v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3820*c2c66affSColin Finck *(sp + 4) = (png_byte)((v >> 8) & 0xff); 3821*c2c66affSColin Finck *(sp + 5) = (png_byte)(v & 0xff); 3822*c2c66affSColin Finck } 3823*c2c66affSColin Finck 3824*c2c66affSColin Finck else if (a == 0) 3825*c2c66affSColin Finck { 3826*c2c66affSColin Finck /* Background is already in screen gamma */ 3827*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 3828*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 3829*c2c66affSColin Finck *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 3830*c2c66affSColin Finck & 0xff); 3831*c2c66affSColin Finck *(sp + 3) = (png_byte)(png_ptr->background.green 3832*c2c66affSColin Finck & 0xff); 3833*c2c66affSColin Finck *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 3834*c2c66affSColin Finck & 0xff); 3835*c2c66affSColin Finck *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 3836*c2c66affSColin Finck } 3837*c2c66affSColin Finck 3838*c2c66affSColin Finck else 3839*c2c66affSColin Finck { 3840*c2c66affSColin Finck png_uint_16 v, w; 3841*c2c66affSColin Finck 3842*c2c66affSColin Finck v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 3843*c2c66affSColin Finck png_composite_16(w, v, a, png_ptr->background_1.red); 3844*c2c66affSColin Finck if (optimize == 0) 3845*c2c66affSColin Finck w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> 3846*c2c66affSColin Finck 8]; 3847*c2c66affSColin Finck *sp = (png_byte)((w >> 8) & 0xff); 3848*c2c66affSColin Finck *(sp + 1) = (png_byte)(w & 0xff); 3849*c2c66affSColin Finck 3850*c2c66affSColin Finck v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3851*c2c66affSColin Finck png_composite_16(w, v, a, png_ptr->background_1.green); 3852*c2c66affSColin Finck if (optimize == 0) 3853*c2c66affSColin Finck w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> 3854*c2c66affSColin Finck 8]; 3855*c2c66affSColin Finck 3856*c2c66affSColin Finck *(sp + 2) = (png_byte)((w >> 8) & 0xff); 3857*c2c66affSColin Finck *(sp + 3) = (png_byte)(w & 0xff); 3858*c2c66affSColin Finck 3859*c2c66affSColin Finck v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3860*c2c66affSColin Finck png_composite_16(w, v, a, png_ptr->background_1.blue); 3861*c2c66affSColin Finck if (optimize == 0) 3862*c2c66affSColin Finck w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> 3863*c2c66affSColin Finck 8]; 3864*c2c66affSColin Finck 3865*c2c66affSColin Finck *(sp + 4) = (png_byte)((w >> 8) & 0xff); 3866*c2c66affSColin Finck *(sp + 5) = (png_byte)(w & 0xff); 3867*c2c66affSColin Finck } 3868*c2c66affSColin Finck } 3869*c2c66affSColin Finck } 3870*c2c66affSColin Finck 3871*c2c66affSColin Finck else 3872*c2c66affSColin Finck #endif 3873*c2c66affSColin Finck { 3874*c2c66affSColin Finck sp = row; 3875*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp += 8) 3876*c2c66affSColin Finck { 3877*c2c66affSColin Finck png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 3878*c2c66affSColin Finck << 8) + (png_uint_16)(*(sp + 7))); 3879*c2c66affSColin Finck 3880*c2c66affSColin Finck if (a == 0) 3881*c2c66affSColin Finck { 3882*c2c66affSColin Finck *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 3883*c2c66affSColin Finck *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 3884*c2c66affSColin Finck *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) 3885*c2c66affSColin Finck & 0xff); 3886*c2c66affSColin Finck *(sp + 3) = (png_byte)(png_ptr->background.green 3887*c2c66affSColin Finck & 0xff); 3888*c2c66affSColin Finck *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) 3889*c2c66affSColin Finck & 0xff); 3890*c2c66affSColin Finck *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 3891*c2c66affSColin Finck } 3892*c2c66affSColin Finck 3893*c2c66affSColin Finck else if (a < 0xffff) 3894*c2c66affSColin Finck { 3895*c2c66affSColin Finck png_uint_16 v; 3896*c2c66affSColin Finck 3897*c2c66affSColin Finck png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3898*c2c66affSColin Finck png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 3899*c2c66affSColin Finck + *(sp + 3)); 3900*c2c66affSColin Finck png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 3901*c2c66affSColin Finck + *(sp + 5)); 3902*c2c66affSColin Finck 3903*c2c66affSColin Finck png_composite_16(v, r, a, png_ptr->background.red); 3904*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3905*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3906*c2c66affSColin Finck 3907*c2c66affSColin Finck png_composite_16(v, g, a, png_ptr->background.green); 3908*c2c66affSColin Finck *(sp + 2) = (png_byte)((v >> 8) & 0xff); 3909*c2c66affSColin Finck *(sp + 3) = (png_byte)(v & 0xff); 3910*c2c66affSColin Finck 3911*c2c66affSColin Finck png_composite_16(v, b, a, png_ptr->background.blue); 3912*c2c66affSColin Finck *(sp + 4) = (png_byte)((v >> 8) & 0xff); 3913*c2c66affSColin Finck *(sp + 5) = (png_byte)(v & 0xff); 3914*c2c66affSColin Finck } 3915*c2c66affSColin Finck } 3916*c2c66affSColin Finck } 3917*c2c66affSColin Finck } 3918*c2c66affSColin Finck break; 3919*c2c66affSColin Finck } 3920*c2c66affSColin Finck 3921*c2c66affSColin Finck default: 3922*c2c66affSColin Finck break; 3923*c2c66affSColin Finck } 3924*c2c66affSColin Finck } 3925*c2c66affSColin Finck } 3926*c2c66affSColin Finck #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ 3927*c2c66affSColin Finck 3928*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 3929*c2c66affSColin Finck /* Gamma correct the image, avoiding the alpha channel. Make sure 3930*c2c66affSColin Finck * you do this after you deal with the transparency issue on grayscale 3931*c2c66affSColin Finck * or RGB images. If your bit depth is 8, use gamma_table, if it 3932*c2c66affSColin Finck * is 16, use gamma_16_table and gamma_shift. Build these with 3933*c2c66affSColin Finck * build_gamma_table(). 3934*c2c66affSColin Finck */ 3935*c2c66affSColin Finck static void 3936*c2c66affSColin Finck png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 3937*c2c66affSColin Finck { 3938*c2c66affSColin Finck png_const_bytep gamma_table = png_ptr->gamma_table; 3939*c2c66affSColin Finck png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; 3940*c2c66affSColin Finck int gamma_shift = png_ptr->gamma_shift; 3941*c2c66affSColin Finck 3942*c2c66affSColin Finck png_bytep sp; 3943*c2c66affSColin Finck png_uint_32 i; 3944*c2c66affSColin Finck png_uint_32 row_width=row_info->width; 3945*c2c66affSColin Finck 3946*c2c66affSColin Finck png_debug(1, "in png_do_gamma"); 3947*c2c66affSColin Finck 3948*c2c66affSColin Finck if (((row_info->bit_depth <= 8 && gamma_table != NULL) || 3949*c2c66affSColin Finck (row_info->bit_depth == 16 && gamma_16_table != NULL))) 3950*c2c66affSColin Finck { 3951*c2c66affSColin Finck switch (row_info->color_type) 3952*c2c66affSColin Finck { 3953*c2c66affSColin Finck case PNG_COLOR_TYPE_RGB: 3954*c2c66affSColin Finck { 3955*c2c66affSColin Finck if (row_info->bit_depth == 8) 3956*c2c66affSColin Finck { 3957*c2c66affSColin Finck sp = row; 3958*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3959*c2c66affSColin Finck { 3960*c2c66affSColin Finck *sp = gamma_table[*sp]; 3961*c2c66affSColin Finck sp++; 3962*c2c66affSColin Finck *sp = gamma_table[*sp]; 3963*c2c66affSColin Finck sp++; 3964*c2c66affSColin Finck *sp = gamma_table[*sp]; 3965*c2c66affSColin Finck sp++; 3966*c2c66affSColin Finck } 3967*c2c66affSColin Finck } 3968*c2c66affSColin Finck 3969*c2c66affSColin Finck else /* if (row_info->bit_depth == 16) */ 3970*c2c66affSColin Finck { 3971*c2c66affSColin Finck sp = row; 3972*c2c66affSColin Finck for (i = 0; i < row_width; i++) 3973*c2c66affSColin Finck { 3974*c2c66affSColin Finck png_uint_16 v; 3975*c2c66affSColin Finck 3976*c2c66affSColin Finck v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3977*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3978*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3979*c2c66affSColin Finck sp += 2; 3980*c2c66affSColin Finck 3981*c2c66affSColin Finck v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3982*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3983*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3984*c2c66affSColin Finck sp += 2; 3985*c2c66affSColin Finck 3986*c2c66affSColin Finck v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3987*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 3988*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 3989*c2c66affSColin Finck sp += 2; 3990*c2c66affSColin Finck } 3991*c2c66affSColin Finck } 3992*c2c66affSColin Finck break; 3993*c2c66affSColin Finck } 3994*c2c66affSColin Finck 3995*c2c66affSColin Finck case PNG_COLOR_TYPE_RGB_ALPHA: 3996*c2c66affSColin Finck { 3997*c2c66affSColin Finck if (row_info->bit_depth == 8) 3998*c2c66affSColin Finck { 3999*c2c66affSColin Finck sp = row; 4000*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4001*c2c66affSColin Finck { 4002*c2c66affSColin Finck *sp = gamma_table[*sp]; 4003*c2c66affSColin Finck sp++; 4004*c2c66affSColin Finck 4005*c2c66affSColin Finck *sp = gamma_table[*sp]; 4006*c2c66affSColin Finck sp++; 4007*c2c66affSColin Finck 4008*c2c66affSColin Finck *sp = gamma_table[*sp]; 4009*c2c66affSColin Finck sp++; 4010*c2c66affSColin Finck 4011*c2c66affSColin Finck sp++; 4012*c2c66affSColin Finck } 4013*c2c66affSColin Finck } 4014*c2c66affSColin Finck 4015*c2c66affSColin Finck else /* if (row_info->bit_depth == 16) */ 4016*c2c66affSColin Finck { 4017*c2c66affSColin Finck sp = row; 4018*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4019*c2c66affSColin Finck { 4020*c2c66affSColin Finck png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 4021*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 4022*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 4023*c2c66affSColin Finck sp += 2; 4024*c2c66affSColin Finck 4025*c2c66affSColin Finck v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 4026*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 4027*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 4028*c2c66affSColin Finck sp += 2; 4029*c2c66affSColin Finck 4030*c2c66affSColin Finck v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 4031*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 4032*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 4033*c2c66affSColin Finck sp += 4; 4034*c2c66affSColin Finck } 4035*c2c66affSColin Finck } 4036*c2c66affSColin Finck break; 4037*c2c66affSColin Finck } 4038*c2c66affSColin Finck 4039*c2c66affSColin Finck case PNG_COLOR_TYPE_GRAY_ALPHA: 4040*c2c66affSColin Finck { 4041*c2c66affSColin Finck if (row_info->bit_depth == 8) 4042*c2c66affSColin Finck { 4043*c2c66affSColin Finck sp = row; 4044*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4045*c2c66affSColin Finck { 4046*c2c66affSColin Finck *sp = gamma_table[*sp]; 4047*c2c66affSColin Finck sp += 2; 4048*c2c66affSColin Finck } 4049*c2c66affSColin Finck } 4050*c2c66affSColin Finck 4051*c2c66affSColin Finck else /* if (row_info->bit_depth == 16) */ 4052*c2c66affSColin Finck { 4053*c2c66affSColin Finck sp = row; 4054*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4055*c2c66affSColin Finck { 4056*c2c66affSColin Finck png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 4057*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 4058*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 4059*c2c66affSColin Finck sp += 4; 4060*c2c66affSColin Finck } 4061*c2c66affSColin Finck } 4062*c2c66affSColin Finck break; 4063*c2c66affSColin Finck } 4064*c2c66affSColin Finck 4065*c2c66affSColin Finck case PNG_COLOR_TYPE_GRAY: 4066*c2c66affSColin Finck { 4067*c2c66affSColin Finck if (row_info->bit_depth == 2) 4068*c2c66affSColin Finck { 4069*c2c66affSColin Finck sp = row; 4070*c2c66affSColin Finck for (i = 0; i < row_width; i += 4) 4071*c2c66affSColin Finck { 4072*c2c66affSColin Finck int a = *sp & 0xc0; 4073*c2c66affSColin Finck int b = *sp & 0x30; 4074*c2c66affSColin Finck int c = *sp & 0x0c; 4075*c2c66affSColin Finck int d = *sp & 0x03; 4076*c2c66affSColin Finck 4077*c2c66affSColin Finck *sp = (png_byte)( 4078*c2c66affSColin Finck ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 4079*c2c66affSColin Finck ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 4080*c2c66affSColin Finck ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 4081*c2c66affSColin Finck ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 4082*c2c66affSColin Finck sp++; 4083*c2c66affSColin Finck } 4084*c2c66affSColin Finck } 4085*c2c66affSColin Finck 4086*c2c66affSColin Finck if (row_info->bit_depth == 4) 4087*c2c66affSColin Finck { 4088*c2c66affSColin Finck sp = row; 4089*c2c66affSColin Finck for (i = 0; i < row_width; i += 2) 4090*c2c66affSColin Finck { 4091*c2c66affSColin Finck int msb = *sp & 0xf0; 4092*c2c66affSColin Finck int lsb = *sp & 0x0f; 4093*c2c66affSColin Finck 4094*c2c66affSColin Finck *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 4095*c2c66affSColin Finck | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 4096*c2c66affSColin Finck sp++; 4097*c2c66affSColin Finck } 4098*c2c66affSColin Finck } 4099*c2c66affSColin Finck 4100*c2c66affSColin Finck else if (row_info->bit_depth == 8) 4101*c2c66affSColin Finck { 4102*c2c66affSColin Finck sp = row; 4103*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4104*c2c66affSColin Finck { 4105*c2c66affSColin Finck *sp = gamma_table[*sp]; 4106*c2c66affSColin Finck sp++; 4107*c2c66affSColin Finck } 4108*c2c66affSColin Finck } 4109*c2c66affSColin Finck 4110*c2c66affSColin Finck else if (row_info->bit_depth == 16) 4111*c2c66affSColin Finck { 4112*c2c66affSColin Finck sp = row; 4113*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4114*c2c66affSColin Finck { 4115*c2c66affSColin Finck png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 4116*c2c66affSColin Finck *sp = (png_byte)((v >> 8) & 0xff); 4117*c2c66affSColin Finck *(sp + 1) = (png_byte)(v & 0xff); 4118*c2c66affSColin Finck sp += 2; 4119*c2c66affSColin Finck } 4120*c2c66affSColin Finck } 4121*c2c66affSColin Finck break; 4122*c2c66affSColin Finck } 4123*c2c66affSColin Finck 4124*c2c66affSColin Finck default: 4125*c2c66affSColin Finck break; 4126*c2c66affSColin Finck } 4127*c2c66affSColin Finck } 4128*c2c66affSColin Finck } 4129*c2c66affSColin Finck #endif 4130*c2c66affSColin Finck 4131*c2c66affSColin Finck #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 4132*c2c66affSColin Finck /* Encode the alpha channel to the output gamma (the input channel is always 4133*c2c66affSColin Finck * linear.) Called only with color types that have an alpha channel. Needs the 4134*c2c66affSColin Finck * from_1 tables. 4135*c2c66affSColin Finck */ 4136*c2c66affSColin Finck static void 4137*c2c66affSColin Finck png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) 4138*c2c66affSColin Finck { 4139*c2c66affSColin Finck png_uint_32 row_width = row_info->width; 4140*c2c66affSColin Finck 4141*c2c66affSColin Finck png_debug(1, "in png_do_encode_alpha"); 4142*c2c66affSColin Finck 4143*c2c66affSColin Finck if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0) 4144*c2c66affSColin Finck { 4145*c2c66affSColin Finck if (row_info->bit_depth == 8) 4146*c2c66affSColin Finck { 4147*c2c66affSColin Finck PNG_CONST png_bytep table = png_ptr->gamma_from_1; 4148*c2c66affSColin Finck 4149*c2c66affSColin Finck if (table != NULL) 4150*c2c66affSColin Finck { 4151*c2c66affSColin Finck PNG_CONST int step = 4152*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; 4153*c2c66affSColin Finck 4154*c2c66affSColin Finck /* The alpha channel is the last component: */ 4155*c2c66affSColin Finck row += step - 1; 4156*c2c66affSColin Finck 4157*c2c66affSColin Finck for (; row_width > 0; --row_width, row += step) 4158*c2c66affSColin Finck *row = table[*row]; 4159*c2c66affSColin Finck 4160*c2c66affSColin Finck return; 4161*c2c66affSColin Finck } 4162*c2c66affSColin Finck } 4163*c2c66affSColin Finck 4164*c2c66affSColin Finck else if (row_info->bit_depth == 16) 4165*c2c66affSColin Finck { 4166*c2c66affSColin Finck PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; 4167*c2c66affSColin Finck PNG_CONST int gamma_shift = png_ptr->gamma_shift; 4168*c2c66affSColin Finck 4169*c2c66affSColin Finck if (table != NULL) 4170*c2c66affSColin Finck { 4171*c2c66affSColin Finck PNG_CONST int step = 4172*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; 4173*c2c66affSColin Finck 4174*c2c66affSColin Finck /* The alpha channel is the last component: */ 4175*c2c66affSColin Finck row += step - 2; 4176*c2c66affSColin Finck 4177*c2c66affSColin Finck for (; row_width > 0; --row_width, row += step) 4178*c2c66affSColin Finck { 4179*c2c66affSColin Finck png_uint_16 v; 4180*c2c66affSColin Finck 4181*c2c66affSColin Finck v = table[*(row + 1) >> gamma_shift][*row]; 4182*c2c66affSColin Finck *row = (png_byte)((v >> 8) & 0xff); 4183*c2c66affSColin Finck *(row + 1) = (png_byte)(v & 0xff); 4184*c2c66affSColin Finck } 4185*c2c66affSColin Finck 4186*c2c66affSColin Finck return; 4187*c2c66affSColin Finck } 4188*c2c66affSColin Finck } 4189*c2c66affSColin Finck } 4190*c2c66affSColin Finck 4191*c2c66affSColin Finck /* Only get to here if called with a weird row_info; no harm has been done, 4192*c2c66affSColin Finck * so just issue a warning. 4193*c2c66affSColin Finck */ 4194*c2c66affSColin Finck png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); 4195*c2c66affSColin Finck } 4196*c2c66affSColin Finck #endif 4197*c2c66affSColin Finck 4198*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_SUPPORTED 4199*c2c66affSColin Finck /* Expands a palette row to an RGB or RGBA row depending 4200*c2c66affSColin Finck * upon whether you supply trans and num_trans. 4201*c2c66affSColin Finck */ 4202*c2c66affSColin Finck static void 4203*c2c66affSColin Finck png_do_expand_palette(png_row_infop row_info, png_bytep row, 4204*c2c66affSColin Finck png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) 4205*c2c66affSColin Finck { 4206*c2c66affSColin Finck int shift, value; 4207*c2c66affSColin Finck png_bytep sp, dp; 4208*c2c66affSColin Finck png_uint_32 i; 4209*c2c66affSColin Finck png_uint_32 row_width=row_info->width; 4210*c2c66affSColin Finck 4211*c2c66affSColin Finck png_debug(1, "in png_do_expand_palette"); 4212*c2c66affSColin Finck 4213*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 4214*c2c66affSColin Finck { 4215*c2c66affSColin Finck if (row_info->bit_depth < 8) 4216*c2c66affSColin Finck { 4217*c2c66affSColin Finck switch (row_info->bit_depth) 4218*c2c66affSColin Finck { 4219*c2c66affSColin Finck case 1: 4220*c2c66affSColin Finck { 4221*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 3); 4222*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4223*c2c66affSColin Finck shift = 7 - (int)((row_width + 7) & 0x07); 4224*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4225*c2c66affSColin Finck { 4226*c2c66affSColin Finck if ((*sp >> shift) & 0x01) 4227*c2c66affSColin Finck *dp = 1; 4228*c2c66affSColin Finck 4229*c2c66affSColin Finck else 4230*c2c66affSColin Finck *dp = 0; 4231*c2c66affSColin Finck 4232*c2c66affSColin Finck if (shift == 7) 4233*c2c66affSColin Finck { 4234*c2c66affSColin Finck shift = 0; 4235*c2c66affSColin Finck sp--; 4236*c2c66affSColin Finck } 4237*c2c66affSColin Finck 4238*c2c66affSColin Finck else 4239*c2c66affSColin Finck shift++; 4240*c2c66affSColin Finck 4241*c2c66affSColin Finck dp--; 4242*c2c66affSColin Finck } 4243*c2c66affSColin Finck break; 4244*c2c66affSColin Finck } 4245*c2c66affSColin Finck 4246*c2c66affSColin Finck case 2: 4247*c2c66affSColin Finck { 4248*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 2); 4249*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4250*c2c66affSColin Finck shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 4251*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4252*c2c66affSColin Finck { 4253*c2c66affSColin Finck value = (*sp >> shift) & 0x03; 4254*c2c66affSColin Finck *dp = (png_byte)value; 4255*c2c66affSColin Finck if (shift == 6) 4256*c2c66affSColin Finck { 4257*c2c66affSColin Finck shift = 0; 4258*c2c66affSColin Finck sp--; 4259*c2c66affSColin Finck } 4260*c2c66affSColin Finck 4261*c2c66affSColin Finck else 4262*c2c66affSColin Finck shift += 2; 4263*c2c66affSColin Finck 4264*c2c66affSColin Finck dp--; 4265*c2c66affSColin Finck } 4266*c2c66affSColin Finck break; 4267*c2c66affSColin Finck } 4268*c2c66affSColin Finck 4269*c2c66affSColin Finck case 4: 4270*c2c66affSColin Finck { 4271*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 1); 4272*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4273*c2c66affSColin Finck shift = (int)((row_width & 0x01) << 2); 4274*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4275*c2c66affSColin Finck { 4276*c2c66affSColin Finck value = (*sp >> shift) & 0x0f; 4277*c2c66affSColin Finck *dp = (png_byte)value; 4278*c2c66affSColin Finck if (shift == 4) 4279*c2c66affSColin Finck { 4280*c2c66affSColin Finck shift = 0; 4281*c2c66affSColin Finck sp--; 4282*c2c66affSColin Finck } 4283*c2c66affSColin Finck 4284*c2c66affSColin Finck else 4285*c2c66affSColin Finck shift += 4; 4286*c2c66affSColin Finck 4287*c2c66affSColin Finck dp--; 4288*c2c66affSColin Finck } 4289*c2c66affSColin Finck break; 4290*c2c66affSColin Finck } 4291*c2c66affSColin Finck 4292*c2c66affSColin Finck default: 4293*c2c66affSColin Finck break; 4294*c2c66affSColin Finck } 4295*c2c66affSColin Finck row_info->bit_depth = 8; 4296*c2c66affSColin Finck row_info->pixel_depth = 8; 4297*c2c66affSColin Finck row_info->rowbytes = row_width; 4298*c2c66affSColin Finck } 4299*c2c66affSColin Finck 4300*c2c66affSColin Finck if (row_info->bit_depth == 8) 4301*c2c66affSColin Finck { 4302*c2c66affSColin Finck { 4303*c2c66affSColin Finck if (num_trans > 0) 4304*c2c66affSColin Finck { 4305*c2c66affSColin Finck sp = row + (png_size_t)row_width - 1; 4306*c2c66affSColin Finck dp = row + ((png_size_t)row_width << 2) - 1; 4307*c2c66affSColin Finck 4308*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4309*c2c66affSColin Finck { 4310*c2c66affSColin Finck if ((int)(*sp) >= num_trans) 4311*c2c66affSColin Finck *dp-- = 0xff; 4312*c2c66affSColin Finck 4313*c2c66affSColin Finck else 4314*c2c66affSColin Finck *dp-- = trans_alpha[*sp]; 4315*c2c66affSColin Finck 4316*c2c66affSColin Finck *dp-- = palette[*sp].blue; 4317*c2c66affSColin Finck *dp-- = palette[*sp].green; 4318*c2c66affSColin Finck *dp-- = palette[*sp].red; 4319*c2c66affSColin Finck sp--; 4320*c2c66affSColin Finck } 4321*c2c66affSColin Finck row_info->bit_depth = 8; 4322*c2c66affSColin Finck row_info->pixel_depth = 32; 4323*c2c66affSColin Finck row_info->rowbytes = row_width * 4; 4324*c2c66affSColin Finck row_info->color_type = 6; 4325*c2c66affSColin Finck row_info->channels = 4; 4326*c2c66affSColin Finck } 4327*c2c66affSColin Finck 4328*c2c66affSColin Finck else 4329*c2c66affSColin Finck { 4330*c2c66affSColin Finck sp = row + (png_size_t)row_width - 1; 4331*c2c66affSColin Finck dp = row + (png_size_t)(row_width * 3) - 1; 4332*c2c66affSColin Finck 4333*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4334*c2c66affSColin Finck { 4335*c2c66affSColin Finck *dp-- = palette[*sp].blue; 4336*c2c66affSColin Finck *dp-- = palette[*sp].green; 4337*c2c66affSColin Finck *dp-- = palette[*sp].red; 4338*c2c66affSColin Finck sp--; 4339*c2c66affSColin Finck } 4340*c2c66affSColin Finck 4341*c2c66affSColin Finck row_info->bit_depth = 8; 4342*c2c66affSColin Finck row_info->pixel_depth = 24; 4343*c2c66affSColin Finck row_info->rowbytes = row_width * 3; 4344*c2c66affSColin Finck row_info->color_type = 2; 4345*c2c66affSColin Finck row_info->channels = 3; 4346*c2c66affSColin Finck } 4347*c2c66affSColin Finck } 4348*c2c66affSColin Finck } 4349*c2c66affSColin Finck } 4350*c2c66affSColin Finck } 4351*c2c66affSColin Finck 4352*c2c66affSColin Finck /* If the bit depth < 8, it is expanded to 8. Also, if the already 4353*c2c66affSColin Finck * expanded transparency value is supplied, an alpha channel is built. 4354*c2c66affSColin Finck */ 4355*c2c66affSColin Finck static void 4356*c2c66affSColin Finck png_do_expand(png_row_infop row_info, png_bytep row, 4357*c2c66affSColin Finck png_const_color_16p trans_color) 4358*c2c66affSColin Finck { 4359*c2c66affSColin Finck int shift, value; 4360*c2c66affSColin Finck png_bytep sp, dp; 4361*c2c66affSColin Finck png_uint_32 i; 4362*c2c66affSColin Finck png_uint_32 row_width=row_info->width; 4363*c2c66affSColin Finck 4364*c2c66affSColin Finck png_debug(1, "in png_do_expand"); 4365*c2c66affSColin Finck 4366*c2c66affSColin Finck { 4367*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 4368*c2c66affSColin Finck { 4369*c2c66affSColin Finck unsigned int gray = trans_color != NULL ? trans_color->gray : 0; 4370*c2c66affSColin Finck 4371*c2c66affSColin Finck if (row_info->bit_depth < 8) 4372*c2c66affSColin Finck { 4373*c2c66affSColin Finck switch (row_info->bit_depth) 4374*c2c66affSColin Finck { 4375*c2c66affSColin Finck case 1: 4376*c2c66affSColin Finck { 4377*c2c66affSColin Finck gray = (gray & 0x01) * 0xff; 4378*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 3); 4379*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4380*c2c66affSColin Finck shift = 7 - (int)((row_width + 7) & 0x07); 4381*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4382*c2c66affSColin Finck { 4383*c2c66affSColin Finck if ((*sp >> shift) & 0x01) 4384*c2c66affSColin Finck *dp = 0xff; 4385*c2c66affSColin Finck 4386*c2c66affSColin Finck else 4387*c2c66affSColin Finck *dp = 0; 4388*c2c66affSColin Finck 4389*c2c66affSColin Finck if (shift == 7) 4390*c2c66affSColin Finck { 4391*c2c66affSColin Finck shift = 0; 4392*c2c66affSColin Finck sp--; 4393*c2c66affSColin Finck } 4394*c2c66affSColin Finck 4395*c2c66affSColin Finck else 4396*c2c66affSColin Finck shift++; 4397*c2c66affSColin Finck 4398*c2c66affSColin Finck dp--; 4399*c2c66affSColin Finck } 4400*c2c66affSColin Finck break; 4401*c2c66affSColin Finck } 4402*c2c66affSColin Finck 4403*c2c66affSColin Finck case 2: 4404*c2c66affSColin Finck { 4405*c2c66affSColin Finck gray = (gray & 0x03) * 0x55; 4406*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 2); 4407*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4408*c2c66affSColin Finck shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 4409*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4410*c2c66affSColin Finck { 4411*c2c66affSColin Finck value = (*sp >> shift) & 0x03; 4412*c2c66affSColin Finck *dp = (png_byte)(value | (value << 2) | (value << 4) | 4413*c2c66affSColin Finck (value << 6)); 4414*c2c66affSColin Finck if (shift == 6) 4415*c2c66affSColin Finck { 4416*c2c66affSColin Finck shift = 0; 4417*c2c66affSColin Finck sp--; 4418*c2c66affSColin Finck } 4419*c2c66affSColin Finck 4420*c2c66affSColin Finck else 4421*c2c66affSColin Finck shift += 2; 4422*c2c66affSColin Finck 4423*c2c66affSColin Finck dp--; 4424*c2c66affSColin Finck } 4425*c2c66affSColin Finck break; 4426*c2c66affSColin Finck } 4427*c2c66affSColin Finck 4428*c2c66affSColin Finck case 4: 4429*c2c66affSColin Finck { 4430*c2c66affSColin Finck gray = (gray & 0x0f) * 0x11; 4431*c2c66affSColin Finck sp = row + (png_size_t)((row_width - 1) >> 1); 4432*c2c66affSColin Finck dp = row + (png_size_t)row_width - 1; 4433*c2c66affSColin Finck shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 4434*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4435*c2c66affSColin Finck { 4436*c2c66affSColin Finck value = (*sp >> shift) & 0x0f; 4437*c2c66affSColin Finck *dp = (png_byte)(value | (value << 4)); 4438*c2c66affSColin Finck if (shift == 4) 4439*c2c66affSColin Finck { 4440*c2c66affSColin Finck shift = 0; 4441*c2c66affSColin Finck sp--; 4442*c2c66affSColin Finck } 4443*c2c66affSColin Finck 4444*c2c66affSColin Finck else 4445*c2c66affSColin Finck shift = 4; 4446*c2c66affSColin Finck 4447*c2c66affSColin Finck dp--; 4448*c2c66affSColin Finck } 4449*c2c66affSColin Finck break; 4450*c2c66affSColin Finck } 4451*c2c66affSColin Finck 4452*c2c66affSColin Finck default: 4453*c2c66affSColin Finck break; 4454*c2c66affSColin Finck } 4455*c2c66affSColin Finck 4456*c2c66affSColin Finck row_info->bit_depth = 8; 4457*c2c66affSColin Finck row_info->pixel_depth = 8; 4458*c2c66affSColin Finck row_info->rowbytes = row_width; 4459*c2c66affSColin Finck } 4460*c2c66affSColin Finck 4461*c2c66affSColin Finck if (trans_color != NULL) 4462*c2c66affSColin Finck { 4463*c2c66affSColin Finck if (row_info->bit_depth == 8) 4464*c2c66affSColin Finck { 4465*c2c66affSColin Finck gray = gray & 0xff; 4466*c2c66affSColin Finck sp = row + (png_size_t)row_width - 1; 4467*c2c66affSColin Finck dp = row + ((png_size_t)row_width << 1) - 1; 4468*c2c66affSColin Finck 4469*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4470*c2c66affSColin Finck { 4471*c2c66affSColin Finck if ((*sp & 0xffU) == gray) 4472*c2c66affSColin Finck *dp-- = 0; 4473*c2c66affSColin Finck 4474*c2c66affSColin Finck else 4475*c2c66affSColin Finck *dp-- = 0xff; 4476*c2c66affSColin Finck 4477*c2c66affSColin Finck *dp-- = *sp--; 4478*c2c66affSColin Finck } 4479*c2c66affSColin Finck } 4480*c2c66affSColin Finck 4481*c2c66affSColin Finck else if (row_info->bit_depth == 16) 4482*c2c66affSColin Finck { 4483*c2c66affSColin Finck unsigned int gray_high = (gray >> 8) & 0xff; 4484*c2c66affSColin Finck unsigned int gray_low = gray & 0xff; 4485*c2c66affSColin Finck sp = row + row_info->rowbytes - 1; 4486*c2c66affSColin Finck dp = row + (row_info->rowbytes << 1) - 1; 4487*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4488*c2c66affSColin Finck { 4489*c2c66affSColin Finck if ((*(sp - 1) & 0xffU) == gray_high && 4490*c2c66affSColin Finck (*(sp) & 0xffU) == gray_low) 4491*c2c66affSColin Finck { 4492*c2c66affSColin Finck *dp-- = 0; 4493*c2c66affSColin Finck *dp-- = 0; 4494*c2c66affSColin Finck } 4495*c2c66affSColin Finck 4496*c2c66affSColin Finck else 4497*c2c66affSColin Finck { 4498*c2c66affSColin Finck *dp-- = 0xff; 4499*c2c66affSColin Finck *dp-- = 0xff; 4500*c2c66affSColin Finck } 4501*c2c66affSColin Finck 4502*c2c66affSColin Finck *dp-- = *sp--; 4503*c2c66affSColin Finck *dp-- = *sp--; 4504*c2c66affSColin Finck } 4505*c2c66affSColin Finck } 4506*c2c66affSColin Finck 4507*c2c66affSColin Finck row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 4508*c2c66affSColin Finck row_info->channels = 2; 4509*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 4510*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 4511*c2c66affSColin Finck row_width); 4512*c2c66affSColin Finck } 4513*c2c66affSColin Finck } 4514*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_RGB && 4515*c2c66affSColin Finck trans_color != NULL) 4516*c2c66affSColin Finck { 4517*c2c66affSColin Finck if (row_info->bit_depth == 8) 4518*c2c66affSColin Finck { 4519*c2c66affSColin Finck png_byte red = (png_byte)(trans_color->red & 0xff); 4520*c2c66affSColin Finck png_byte green = (png_byte)(trans_color->green & 0xff); 4521*c2c66affSColin Finck png_byte blue = (png_byte)(trans_color->blue & 0xff); 4522*c2c66affSColin Finck sp = row + (png_size_t)row_info->rowbytes - 1; 4523*c2c66affSColin Finck dp = row + ((png_size_t)row_width << 2) - 1; 4524*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4525*c2c66affSColin Finck { 4526*c2c66affSColin Finck if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 4527*c2c66affSColin Finck *dp-- = 0; 4528*c2c66affSColin Finck 4529*c2c66affSColin Finck else 4530*c2c66affSColin Finck *dp-- = 0xff; 4531*c2c66affSColin Finck 4532*c2c66affSColin Finck *dp-- = *sp--; 4533*c2c66affSColin Finck *dp-- = *sp--; 4534*c2c66affSColin Finck *dp-- = *sp--; 4535*c2c66affSColin Finck } 4536*c2c66affSColin Finck } 4537*c2c66affSColin Finck else if (row_info->bit_depth == 16) 4538*c2c66affSColin Finck { 4539*c2c66affSColin Finck png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); 4540*c2c66affSColin Finck png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); 4541*c2c66affSColin Finck png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); 4542*c2c66affSColin Finck png_byte red_low = (png_byte)(trans_color->red & 0xff); 4543*c2c66affSColin Finck png_byte green_low = (png_byte)(trans_color->green & 0xff); 4544*c2c66affSColin Finck png_byte blue_low = (png_byte)(trans_color->blue & 0xff); 4545*c2c66affSColin Finck sp = row + row_info->rowbytes - 1; 4546*c2c66affSColin Finck dp = row + ((png_size_t)row_width << 3) - 1; 4547*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4548*c2c66affSColin Finck { 4549*c2c66affSColin Finck if (*(sp - 5) == red_high && 4550*c2c66affSColin Finck *(sp - 4) == red_low && 4551*c2c66affSColin Finck *(sp - 3) == green_high && 4552*c2c66affSColin Finck *(sp - 2) == green_low && 4553*c2c66affSColin Finck *(sp - 1) == blue_high && 4554*c2c66affSColin Finck *(sp ) == blue_low) 4555*c2c66affSColin Finck { 4556*c2c66affSColin Finck *dp-- = 0; 4557*c2c66affSColin Finck *dp-- = 0; 4558*c2c66affSColin Finck } 4559*c2c66affSColin Finck 4560*c2c66affSColin Finck else 4561*c2c66affSColin Finck { 4562*c2c66affSColin Finck *dp-- = 0xff; 4563*c2c66affSColin Finck *dp-- = 0xff; 4564*c2c66affSColin Finck } 4565*c2c66affSColin Finck 4566*c2c66affSColin Finck *dp-- = *sp--; 4567*c2c66affSColin Finck *dp-- = *sp--; 4568*c2c66affSColin Finck *dp-- = *sp--; 4569*c2c66affSColin Finck *dp-- = *sp--; 4570*c2c66affSColin Finck *dp-- = *sp--; 4571*c2c66affSColin Finck *dp-- = *sp--; 4572*c2c66affSColin Finck } 4573*c2c66affSColin Finck } 4574*c2c66affSColin Finck row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 4575*c2c66affSColin Finck row_info->channels = 4; 4576*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 4577*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4578*c2c66affSColin Finck } 4579*c2c66affSColin Finck } 4580*c2c66affSColin Finck } 4581*c2c66affSColin Finck #endif 4582*c2c66affSColin Finck 4583*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_16_SUPPORTED 4584*c2c66affSColin Finck /* If the bit depth is 8 and the color type is not a palette type expand the 4585*c2c66affSColin Finck * whole row to 16 bits. Has no effect otherwise. 4586*c2c66affSColin Finck */ 4587*c2c66affSColin Finck static void 4588*c2c66affSColin Finck png_do_expand_16(png_row_infop row_info, png_bytep row) 4589*c2c66affSColin Finck { 4590*c2c66affSColin Finck if (row_info->bit_depth == 8 && 4591*c2c66affSColin Finck row_info->color_type != PNG_COLOR_TYPE_PALETTE) 4592*c2c66affSColin Finck { 4593*c2c66affSColin Finck /* The row have a sequence of bytes containing [0..255] and we need 4594*c2c66affSColin Finck * to turn it into another row containing [0..65535], to do this we 4595*c2c66affSColin Finck * calculate: 4596*c2c66affSColin Finck * 4597*c2c66affSColin Finck * (input / 255) * 65535 4598*c2c66affSColin Finck * 4599*c2c66affSColin Finck * Which happens to be exactly input * 257 and this can be achieved 4600*c2c66affSColin Finck * simply by byte replication in place (copying backwards). 4601*c2c66affSColin Finck */ 4602*c2c66affSColin Finck png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ 4603*c2c66affSColin Finck png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ 4604*c2c66affSColin Finck while (dp > sp) 4605*c2c66affSColin Finck { 4606*c2c66affSColin Finck dp[-2] = dp[-1] = *--sp; dp -= 2; 4607*c2c66affSColin Finck } 4608*c2c66affSColin Finck 4609*c2c66affSColin Finck row_info->rowbytes *= 2; 4610*c2c66affSColin Finck row_info->bit_depth = 16; 4611*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->channels * 16); 4612*c2c66affSColin Finck } 4613*c2c66affSColin Finck } 4614*c2c66affSColin Finck #endif 4615*c2c66affSColin Finck 4616*c2c66affSColin Finck #ifdef PNG_READ_QUANTIZE_SUPPORTED 4617*c2c66affSColin Finck static void 4618*c2c66affSColin Finck png_do_quantize(png_row_infop row_info, png_bytep row, 4619*c2c66affSColin Finck png_const_bytep palette_lookup, png_const_bytep quantize_lookup) 4620*c2c66affSColin Finck { 4621*c2c66affSColin Finck png_bytep sp, dp; 4622*c2c66affSColin Finck png_uint_32 i; 4623*c2c66affSColin Finck png_uint_32 row_width=row_info->width; 4624*c2c66affSColin Finck 4625*c2c66affSColin Finck png_debug(1, "in png_do_quantize"); 4626*c2c66affSColin Finck 4627*c2c66affSColin Finck if (row_info->bit_depth == 8) 4628*c2c66affSColin Finck { 4629*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) 4630*c2c66affSColin Finck { 4631*c2c66affSColin Finck int r, g, b, p; 4632*c2c66affSColin Finck sp = row; 4633*c2c66affSColin Finck dp = row; 4634*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4635*c2c66affSColin Finck { 4636*c2c66affSColin Finck r = *sp++; 4637*c2c66affSColin Finck g = *sp++; 4638*c2c66affSColin Finck b = *sp++; 4639*c2c66affSColin Finck 4640*c2c66affSColin Finck /* This looks real messy, but the compiler will reduce 4641*c2c66affSColin Finck * it down to a reasonable formula. For example, with 4642*c2c66affSColin Finck * 5 bits per color, we get: 4643*c2c66affSColin Finck * p = (((r >> 3) & 0x1f) << 10) | 4644*c2c66affSColin Finck * (((g >> 3) & 0x1f) << 5) | 4645*c2c66affSColin Finck * ((b >> 3) & 0x1f); 4646*c2c66affSColin Finck */ 4647*c2c66affSColin Finck p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 4648*c2c66affSColin Finck ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 4649*c2c66affSColin Finck (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 4650*c2c66affSColin Finck (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 4651*c2c66affSColin Finck ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 4652*c2c66affSColin Finck (PNG_QUANTIZE_BLUE_BITS)) | 4653*c2c66affSColin Finck ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 4654*c2c66affSColin Finck ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 4655*c2c66affSColin Finck 4656*c2c66affSColin Finck *dp++ = palette_lookup[p]; 4657*c2c66affSColin Finck } 4658*c2c66affSColin Finck 4659*c2c66affSColin Finck row_info->color_type = PNG_COLOR_TYPE_PALETTE; 4660*c2c66affSColin Finck row_info->channels = 1; 4661*c2c66affSColin Finck row_info->pixel_depth = row_info->bit_depth; 4662*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4663*c2c66affSColin Finck } 4664*c2c66affSColin Finck 4665*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 4666*c2c66affSColin Finck palette_lookup != NULL) 4667*c2c66affSColin Finck { 4668*c2c66affSColin Finck int r, g, b, p; 4669*c2c66affSColin Finck sp = row; 4670*c2c66affSColin Finck dp = row; 4671*c2c66affSColin Finck for (i = 0; i < row_width; i++) 4672*c2c66affSColin Finck { 4673*c2c66affSColin Finck r = *sp++; 4674*c2c66affSColin Finck g = *sp++; 4675*c2c66affSColin Finck b = *sp++; 4676*c2c66affSColin Finck sp++; 4677*c2c66affSColin Finck 4678*c2c66affSColin Finck p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 4679*c2c66affSColin Finck ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 4680*c2c66affSColin Finck (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 4681*c2c66affSColin Finck (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 4682*c2c66affSColin Finck ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 4683*c2c66affSColin Finck (PNG_QUANTIZE_BLUE_BITS)) | 4684*c2c66affSColin Finck ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 4685*c2c66affSColin Finck ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 4686*c2c66affSColin Finck 4687*c2c66affSColin Finck *dp++ = palette_lookup[p]; 4688*c2c66affSColin Finck } 4689*c2c66affSColin Finck 4690*c2c66affSColin Finck row_info->color_type = PNG_COLOR_TYPE_PALETTE; 4691*c2c66affSColin Finck row_info->channels = 1; 4692*c2c66affSColin Finck row_info->pixel_depth = row_info->bit_depth; 4693*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4694*c2c66affSColin Finck } 4695*c2c66affSColin Finck 4696*c2c66affSColin Finck else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 4697*c2c66affSColin Finck quantize_lookup) 4698*c2c66affSColin Finck { 4699*c2c66affSColin Finck sp = row; 4700*c2c66affSColin Finck 4701*c2c66affSColin Finck for (i = 0; i < row_width; i++, sp++) 4702*c2c66affSColin Finck { 4703*c2c66affSColin Finck *sp = quantize_lookup[*sp]; 4704*c2c66affSColin Finck } 4705*c2c66affSColin Finck } 4706*c2c66affSColin Finck } 4707*c2c66affSColin Finck } 4708*c2c66affSColin Finck #endif /* READ_QUANTIZE */ 4709*c2c66affSColin Finck 4710*c2c66affSColin Finck /* Transform the row. The order of transformations is significant, 4711*c2c66affSColin Finck * and is very touchy. If you add a transformation, take care to 4712*c2c66affSColin Finck * decide how it fits in with the other transformations here. 4713*c2c66affSColin Finck */ 4714*c2c66affSColin Finck void /* PRIVATE */ 4715*c2c66affSColin Finck png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) 4716*c2c66affSColin Finck { 4717*c2c66affSColin Finck png_debug(1, "in png_do_read_transformations"); 4718*c2c66affSColin Finck 4719*c2c66affSColin Finck if (png_ptr->row_buf == NULL) 4720*c2c66affSColin Finck { 4721*c2c66affSColin Finck /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this 4722*c2c66affSColin Finck * error is incredibly rare and incredibly easy to debug without this 4723*c2c66affSColin Finck * information. 4724*c2c66affSColin Finck */ 4725*c2c66affSColin Finck png_error(png_ptr, "NULL row buffer"); 4726*c2c66affSColin Finck } 4727*c2c66affSColin Finck 4728*c2c66affSColin Finck /* The following is debugging; prior to 1.5.4 the code was never compiled in; 4729*c2c66affSColin Finck * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro 4730*c2c66affSColin Finck * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for 4731*c2c66affSColin Finck * all transformations, however in practice the ROW_INIT always gets done on 4732*c2c66affSColin Finck * demand, if necessary. 4733*c2c66affSColin Finck */ 4734*c2c66affSColin Finck if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && 4735*c2c66affSColin Finck (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 4736*c2c66affSColin Finck { 4737*c2c66affSColin Finck /* Application has failed to call either png_read_start_image() or 4738*c2c66affSColin Finck * png_read_update_info() after setting transforms that expand pixels. 4739*c2c66affSColin Finck * This check added to libpng-1.2.19 (but not enabled until 1.5.4). 4740*c2c66affSColin Finck */ 4741*c2c66affSColin Finck png_error(png_ptr, "Uninitialized row"); 4742*c2c66affSColin Finck } 4743*c2c66affSColin Finck 4744*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_SUPPORTED 4745*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND) != 0) 4746*c2c66affSColin Finck { 4747*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 4748*c2c66affSColin Finck { 4749*c2c66affSColin Finck png_do_expand_palette(row_info, png_ptr->row_buf + 1, 4750*c2c66affSColin Finck png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); 4751*c2c66affSColin Finck } 4752*c2c66affSColin Finck 4753*c2c66affSColin Finck else 4754*c2c66affSColin Finck { 4755*c2c66affSColin Finck if (png_ptr->num_trans != 0 && 4756*c2c66affSColin Finck (png_ptr->transformations & PNG_EXPAND_tRNS) != 0) 4757*c2c66affSColin Finck png_do_expand(row_info, png_ptr->row_buf + 1, 4758*c2c66affSColin Finck &(png_ptr->trans_color)); 4759*c2c66affSColin Finck 4760*c2c66affSColin Finck else 4761*c2c66affSColin Finck png_do_expand(row_info, png_ptr->row_buf + 1, 4762*c2c66affSColin Finck NULL); 4763*c2c66affSColin Finck } 4764*c2c66affSColin Finck } 4765*c2c66affSColin Finck #endif 4766*c2c66affSColin Finck 4767*c2c66affSColin Finck #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 4768*c2c66affSColin Finck if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 && 4769*c2c66affSColin Finck (png_ptr->transformations & PNG_COMPOSE) == 0 && 4770*c2c66affSColin Finck (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 4771*c2c66affSColin Finck row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 4772*c2c66affSColin Finck png_do_strip_channel(row_info, png_ptr->row_buf + 1, 4773*c2c66affSColin Finck 0 /* at_start == false, because SWAP_ALPHA happens later */); 4774*c2c66affSColin Finck #endif 4775*c2c66affSColin Finck 4776*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 4777*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) 4778*c2c66affSColin Finck { 4779*c2c66affSColin Finck int rgb_error = 4780*c2c66affSColin Finck png_do_rgb_to_gray(png_ptr, row_info, 4781*c2c66affSColin Finck png_ptr->row_buf + 1); 4782*c2c66affSColin Finck 4783*c2c66affSColin Finck if (rgb_error != 0) 4784*c2c66affSColin Finck { 4785*c2c66affSColin Finck png_ptr->rgb_to_gray_status=1; 4786*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 4787*c2c66affSColin Finck PNG_RGB_TO_GRAY_WARN) 4788*c2c66affSColin Finck png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 4789*c2c66affSColin Finck 4790*c2c66affSColin Finck if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 4791*c2c66affSColin Finck PNG_RGB_TO_GRAY_ERR) 4792*c2c66affSColin Finck png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 4793*c2c66affSColin Finck } 4794*c2c66affSColin Finck } 4795*c2c66affSColin Finck #endif 4796*c2c66affSColin Finck 4797*c2c66affSColin Finck /* From Andreas Dilger e-mail to png-implement, 26 March 1998: 4798*c2c66affSColin Finck * 4799*c2c66affSColin Finck * In most cases, the "simple transparency" should be done prior to doing 4800*c2c66affSColin Finck * gray-to-RGB, or you will have to test 3x as many bytes to check if a 4801*c2c66affSColin Finck * pixel is transparent. You would also need to make sure that the 4802*c2c66affSColin Finck * transparency information is upgraded to RGB. 4803*c2c66affSColin Finck * 4804*c2c66affSColin Finck * To summarize, the current flow is: 4805*c2c66affSColin Finck * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 4806*c2c66affSColin Finck * with background "in place" if transparent, 4807*c2c66affSColin Finck * convert to RGB if necessary 4808*c2c66affSColin Finck * - Gray + alpha -> composite with gray background and remove alpha bytes, 4809*c2c66affSColin Finck * convert to RGB if necessary 4810*c2c66affSColin Finck * 4811*c2c66affSColin Finck * To support RGB backgrounds for gray images we need: 4812*c2c66affSColin Finck * - Gray + simple transparency -> convert to RGB + simple transparency, 4813*c2c66affSColin Finck * compare 3 or 6 bytes and composite with 4814*c2c66affSColin Finck * background "in place" if transparent 4815*c2c66affSColin Finck * (3x compare/pixel compared to doing 4816*c2c66affSColin Finck * composite with gray bkgrnd) 4817*c2c66affSColin Finck * - Gray + alpha -> convert to RGB + alpha, composite with background and 4818*c2c66affSColin Finck * remove alpha bytes (3x float 4819*c2c66affSColin Finck * operations/pixel compared with composite 4820*c2c66affSColin Finck * on gray background) 4821*c2c66affSColin Finck * 4822*c2c66affSColin Finck * Greg's change will do this. The reason it wasn't done before is for 4823*c2c66affSColin Finck * performance, as this increases the per-pixel operations. If we would check 4824*c2c66affSColin Finck * in advance if the background was gray or RGB, and position the gray-to-RGB 4825*c2c66affSColin Finck * transform appropriately, then it would save a lot of work/time. 4826*c2c66affSColin Finck */ 4827*c2c66affSColin Finck 4828*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 4829*c2c66affSColin Finck /* If gray -> RGB, do so now only if background is non-gray; else do later 4830*c2c66affSColin Finck * for performance reasons 4831*c2c66affSColin Finck */ 4832*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 && 4833*c2c66affSColin Finck (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0) 4834*c2c66affSColin Finck png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 4835*c2c66affSColin Finck #endif 4836*c2c66affSColin Finck 4837*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 4838*c2c66affSColin Finck defined(PNG_READ_ALPHA_MODE_SUPPORTED) 4839*c2c66affSColin Finck if ((png_ptr->transformations & PNG_COMPOSE) != 0) 4840*c2c66affSColin Finck png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); 4841*c2c66affSColin Finck #endif 4842*c2c66affSColin Finck 4843*c2c66affSColin Finck #ifdef PNG_READ_GAMMA_SUPPORTED 4844*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GAMMA) != 0 && 4845*c2c66affSColin Finck #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 4846*c2c66affSColin Finck /* Because RGB_TO_GRAY does the gamma transform. */ 4847*c2c66affSColin Finck (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 && 4848*c2c66affSColin Finck #endif 4849*c2c66affSColin Finck #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 4850*c2c66affSColin Finck defined(PNG_READ_ALPHA_MODE_SUPPORTED) 4851*c2c66affSColin Finck /* Because PNG_COMPOSE does the gamma transform if there is something to 4852*c2c66affSColin Finck * do (if there is an alpha channel or transparency.) 4853*c2c66affSColin Finck */ 4854*c2c66affSColin Finck !((png_ptr->transformations & PNG_COMPOSE) != 0 && 4855*c2c66affSColin Finck ((png_ptr->num_trans != 0) || 4856*c2c66affSColin Finck (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) && 4857*c2c66affSColin Finck #endif 4858*c2c66affSColin Finck /* Because png_init_read_transformations transforms the palette, unless 4859*c2c66affSColin Finck * RGB_TO_GRAY will do the transform. 4860*c2c66affSColin Finck */ 4861*c2c66affSColin Finck (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 4862*c2c66affSColin Finck png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); 4863*c2c66affSColin Finck #endif 4864*c2c66affSColin Finck 4865*c2c66affSColin Finck #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 4866*c2c66affSColin Finck if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 && 4867*c2c66affSColin Finck (png_ptr->transformations & PNG_COMPOSE) != 0 && 4868*c2c66affSColin Finck (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 4869*c2c66affSColin Finck row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 4870*c2c66affSColin Finck png_do_strip_channel(row_info, png_ptr->row_buf + 1, 4871*c2c66affSColin Finck 0 /* at_start == false, because SWAP_ALPHA happens later */); 4872*c2c66affSColin Finck #endif 4873*c2c66affSColin Finck 4874*c2c66affSColin Finck #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 4875*c2c66affSColin Finck if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 && 4876*c2c66affSColin Finck (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0) 4877*c2c66affSColin Finck png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); 4878*c2c66affSColin Finck #endif 4879*c2c66affSColin Finck 4880*c2c66affSColin Finck #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 4881*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0) 4882*c2c66affSColin Finck png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); 4883*c2c66affSColin Finck #endif 4884*c2c66affSColin Finck 4885*c2c66affSColin Finck #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 4886*c2c66affSColin Finck /* There is no harm in doing both of these because only one has any effect, 4887*c2c66affSColin Finck * by putting the 'scale' option first if the app asks for scale (either by 4888*c2c66affSColin Finck * calling the API or in a TRANSFORM flag) this is what happens. 4889*c2c66affSColin Finck */ 4890*c2c66affSColin Finck if ((png_ptr->transformations & PNG_16_TO_8) != 0) 4891*c2c66affSColin Finck png_do_chop(row_info, png_ptr->row_buf + 1); 4892*c2c66affSColin Finck #endif 4893*c2c66affSColin Finck 4894*c2c66affSColin Finck #ifdef PNG_READ_QUANTIZE_SUPPORTED 4895*c2c66affSColin Finck if ((png_ptr->transformations & PNG_QUANTIZE) != 0) 4896*c2c66affSColin Finck { 4897*c2c66affSColin Finck png_do_quantize(row_info, png_ptr->row_buf + 1, 4898*c2c66affSColin Finck png_ptr->palette_lookup, png_ptr->quantize_index); 4899*c2c66affSColin Finck 4900*c2c66affSColin Finck if (row_info->rowbytes == 0) 4901*c2c66affSColin Finck png_error(png_ptr, "png_do_quantize returned rowbytes=0"); 4902*c2c66affSColin Finck } 4903*c2c66affSColin Finck #endif /* READ_QUANTIZE */ 4904*c2c66affSColin Finck 4905*c2c66affSColin Finck #ifdef PNG_READ_EXPAND_16_SUPPORTED 4906*c2c66affSColin Finck /* Do the expansion now, after all the arithmetic has been done. Notice 4907*c2c66affSColin Finck * that previous transformations can handle the PNG_EXPAND_16 flag if this 4908*c2c66affSColin Finck * is efficient (particularly true in the case of gamma correction, where 4909*c2c66affSColin Finck * better accuracy results faster!) 4910*c2c66affSColin Finck */ 4911*c2c66affSColin Finck if ((png_ptr->transformations & PNG_EXPAND_16) != 0) 4912*c2c66affSColin Finck png_do_expand_16(row_info, png_ptr->row_buf + 1); 4913*c2c66affSColin Finck #endif 4914*c2c66affSColin Finck 4915*c2c66affSColin Finck #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 4916*c2c66affSColin Finck /* NOTE: moved here in 1.5.4 (from much later in this list.) */ 4917*c2c66affSColin Finck if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 && 4918*c2c66affSColin Finck (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0) 4919*c2c66affSColin Finck png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 4920*c2c66affSColin Finck #endif 4921*c2c66affSColin Finck 4922*c2c66affSColin Finck #ifdef PNG_READ_INVERT_SUPPORTED 4923*c2c66affSColin Finck if ((png_ptr->transformations & PNG_INVERT_MONO) != 0) 4924*c2c66affSColin Finck png_do_invert(row_info, png_ptr->row_buf + 1); 4925*c2c66affSColin Finck #endif 4926*c2c66affSColin Finck 4927*c2c66affSColin Finck #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 4928*c2c66affSColin Finck if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) 4929*c2c66affSColin Finck png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); 4930*c2c66affSColin Finck #endif 4931*c2c66affSColin Finck 4932*c2c66affSColin Finck #ifdef PNG_READ_SHIFT_SUPPORTED 4933*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SHIFT) != 0) 4934*c2c66affSColin Finck png_do_unshift(row_info, png_ptr->row_buf + 1, 4935*c2c66affSColin Finck &(png_ptr->shift)); 4936*c2c66affSColin Finck #endif 4937*c2c66affSColin Finck 4938*c2c66affSColin Finck #ifdef PNG_READ_PACK_SUPPORTED 4939*c2c66affSColin Finck if ((png_ptr->transformations & PNG_PACK) != 0) 4940*c2c66affSColin Finck png_do_unpack(row_info, png_ptr->row_buf + 1); 4941*c2c66affSColin Finck #endif 4942*c2c66affSColin Finck 4943*c2c66affSColin Finck #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED 4944*c2c66affSColin Finck /* Added at libpng-1.5.10 */ 4945*c2c66affSColin Finck if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 4946*c2c66affSColin Finck png_ptr->num_palette_max >= 0) 4947*c2c66affSColin Finck png_do_check_palette_indexes(png_ptr, row_info); 4948*c2c66affSColin Finck #endif 4949*c2c66affSColin Finck 4950*c2c66affSColin Finck #ifdef PNG_READ_BGR_SUPPORTED 4951*c2c66affSColin Finck if ((png_ptr->transformations & PNG_BGR) != 0) 4952*c2c66affSColin Finck png_do_bgr(row_info, png_ptr->row_buf + 1); 4953*c2c66affSColin Finck #endif 4954*c2c66affSColin Finck 4955*c2c66affSColin Finck #ifdef PNG_READ_PACKSWAP_SUPPORTED 4956*c2c66affSColin Finck if ((png_ptr->transformations & PNG_PACKSWAP) != 0) 4957*c2c66affSColin Finck png_do_packswap(row_info, png_ptr->row_buf + 1); 4958*c2c66affSColin Finck #endif 4959*c2c66affSColin Finck 4960*c2c66affSColin Finck #ifdef PNG_READ_FILLER_SUPPORTED 4961*c2c66affSColin Finck if ((png_ptr->transformations & PNG_FILLER) != 0) 4962*c2c66affSColin Finck png_do_read_filler(row_info, png_ptr->row_buf + 1, 4963*c2c66affSColin Finck (png_uint_32)png_ptr->filler, png_ptr->flags); 4964*c2c66affSColin Finck #endif 4965*c2c66affSColin Finck 4966*c2c66affSColin Finck #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 4967*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0) 4968*c2c66affSColin Finck png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); 4969*c2c66affSColin Finck #endif 4970*c2c66affSColin Finck 4971*c2c66affSColin Finck #ifdef PNG_READ_16BIT_SUPPORTED 4972*c2c66affSColin Finck #ifdef PNG_READ_SWAP_SUPPORTED 4973*c2c66affSColin Finck if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0) 4974*c2c66affSColin Finck png_do_swap(row_info, png_ptr->row_buf + 1); 4975*c2c66affSColin Finck #endif 4976*c2c66affSColin Finck #endif 4977*c2c66affSColin Finck 4978*c2c66affSColin Finck #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 4979*c2c66affSColin Finck if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) 4980*c2c66affSColin Finck { 4981*c2c66affSColin Finck if (png_ptr->read_user_transform_fn != NULL) 4982*c2c66affSColin Finck (*(png_ptr->read_user_transform_fn)) /* User read transform function */ 4983*c2c66affSColin Finck (png_ptr, /* png_ptr */ 4984*c2c66affSColin Finck row_info, /* row_info: */ 4985*c2c66affSColin Finck /* png_uint_32 width; width of row */ 4986*c2c66affSColin Finck /* png_size_t rowbytes; number of bytes in row */ 4987*c2c66affSColin Finck /* png_byte color_type; color type of pixels */ 4988*c2c66affSColin Finck /* png_byte bit_depth; bit depth of samples */ 4989*c2c66affSColin Finck /* png_byte channels; number of channels (1-4) */ 4990*c2c66affSColin Finck /* png_byte pixel_depth; bits per pixel (depth*channels) */ 4991*c2c66affSColin Finck png_ptr->row_buf + 1); /* start of pixel data for row */ 4992*c2c66affSColin Finck #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED 4993*c2c66affSColin Finck if (png_ptr->user_transform_depth != 0) 4994*c2c66affSColin Finck row_info->bit_depth = png_ptr->user_transform_depth; 4995*c2c66affSColin Finck 4996*c2c66affSColin Finck if (png_ptr->user_transform_channels != 0) 4997*c2c66affSColin Finck row_info->channels = png_ptr->user_transform_channels; 4998*c2c66affSColin Finck #endif 4999*c2c66affSColin Finck row_info->pixel_depth = (png_byte)(row_info->bit_depth * 5000*c2c66affSColin Finck row_info->channels); 5001*c2c66affSColin Finck 5002*c2c66affSColin Finck row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); 5003*c2c66affSColin Finck } 5004*c2c66affSColin Finck #endif 5005*c2c66affSColin Finck } 5006*c2c66affSColin Finck 5007*c2c66affSColin Finck #endif /* READ_TRANSFORMS */ 5008*c2c66affSColin Finck #endif /* READ */ 5009