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