Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpngrtran.c
Go to the documentation of this file.
00001 00002 /* pngrtran.c - transforms the data in a row for PNG readers 00003 * 00004 * Last changed in libpng 1.5.7 [December 15, 2011] 00005 * Copyright (c) 1998-2011 Glenn Randers-Pehrson 00006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 00007 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 00008 * 00009 * This code is released under the libpng license. 00010 * For conditions of distribution and use, see the disclaimer 00011 * and license in png.h 00012 * 00013 * This file contains functions optionally called by an application 00014 * in order to tell libpng how to handle data when reading a PNG. 00015 * Transformations that are used in both reading and writing are 00016 * in pngtrans.c. 00017 */ 00018 00019 #include "pngpriv.h" 00020 00021 #ifdef PNG_READ_SUPPORTED 00022 00023 /* Set the action on getting a CRC error for an ancillary or critical chunk. */ 00024 void PNGAPI 00025 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) 00026 { 00027 png_debug(1, "in png_set_crc_action"); 00028 00029 if (png_ptr == NULL) 00030 return; 00031 00032 /* Tell libpng how we react to CRC errors in critical chunks */ 00033 switch (crit_action) 00034 { 00035 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 00036 break; 00037 00038 case PNG_CRC_WARN_USE: /* Warn/use data */ 00039 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00040 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 00041 break; 00042 00043 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 00044 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00045 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 00046 PNG_FLAG_CRC_CRITICAL_IGNORE; 00047 break; 00048 00049 case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ 00050 png_warning(png_ptr, 00051 "Can't discard critical data on CRC error"); 00052 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 00053 00054 case PNG_CRC_DEFAULT: 00055 default: 00056 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00057 break; 00058 } 00059 00060 /* Tell libpng how we react to CRC errors in ancillary chunks */ 00061 switch (ancil_action) 00062 { 00063 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 00064 break; 00065 00066 case PNG_CRC_WARN_USE: /* Warn/use data */ 00067 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00068 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 00069 break; 00070 00071 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 00072 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00073 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 00074 PNG_FLAG_CRC_ANCILLARY_NOWARN; 00075 break; 00076 00077 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 00078 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00079 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 00080 break; 00081 00082 case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ 00083 00084 case PNG_CRC_DEFAULT: 00085 default: 00086 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00087 break; 00088 } 00089 } 00090 00091 #ifdef PNG_READ_BACKGROUND_SUPPORTED 00092 /* Handle alpha and tRNS via a background color */ 00093 void PNGFAPI 00094 png_set_background_fixed(png_structp png_ptr, 00095 png_const_color_16p background_color, int background_gamma_code, 00096 int need_expand, png_fixed_point background_gamma) 00097 { 00098 png_debug(1, "in png_set_background_fixed"); 00099 00100 if (png_ptr == NULL) 00101 return; 00102 00103 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 00104 { 00105 png_warning(png_ptr, "Application must supply a known background gamma"); 00106 return; 00107 } 00108 00109 png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; 00110 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 00111 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 00112 00113 png_memcpy(&(png_ptr->background), background_color, 00114 png_sizeof(png_color_16)); 00115 png_ptr->background_gamma = background_gamma; 00116 png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 00117 if (need_expand) 00118 png_ptr->transformations |= PNG_BACKGROUND_EXPAND; 00119 else 00120 png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 00121 } 00122 00123 # ifdef PNG_FLOATING_POINT_SUPPORTED 00124 void PNGAPI 00125 png_set_background(png_structp png_ptr, 00126 png_const_color_16p background_color, int background_gamma_code, 00127 int need_expand, double background_gamma) 00128 { 00129 png_set_background_fixed(png_ptr, background_color, background_gamma_code, 00130 need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); 00131 } 00132 # endif /* FLOATING_POINT */ 00133 #endif /* READ_BACKGROUND */ 00134 00135 /* Scale 16-bit depth files to 8-bit depth. If both of these are set then the 00136 * one that pngrtran does first (scale) happens. This is necessary to allow the 00137 * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. 00138 */ 00139 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 00140 void PNGAPI 00141 png_set_scale_16(png_structp png_ptr) 00142 { 00143 png_debug(1, "in png_set_scale_16"); 00144 00145 if (png_ptr == NULL) 00146 return; 00147 00148 png_ptr->transformations |= PNG_SCALE_16_TO_8; 00149 } 00150 #endif 00151 00152 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 00153 /* Chop 16-bit depth files to 8-bit depth */ 00154 void PNGAPI 00155 png_set_strip_16(png_structp png_ptr) 00156 { 00157 png_debug(1, "in png_set_strip_16"); 00158 00159 if (png_ptr == NULL) 00160 return; 00161 00162 png_ptr->transformations |= PNG_16_TO_8; 00163 } 00164 #endif 00165 00166 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 00167 void PNGAPI 00168 png_set_strip_alpha(png_structp png_ptr) 00169 { 00170 png_debug(1, "in png_set_strip_alpha"); 00171 00172 if (png_ptr == NULL) 00173 return; 00174 00175 png_ptr->transformations |= PNG_STRIP_ALPHA; 00176 } 00177 #endif 00178 00179 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) 00180 static png_fixed_point 00181 translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, 00182 int is_screen) 00183 { 00184 /* Check for flag values. The main reason for having the old Mac value as a 00185 * flag is that it is pretty near impossible to work out what the correct 00186 * value is from Apple documentation - a working Mac system is needed to 00187 * discover the value! 00188 */ 00189 if (output_gamma == PNG_DEFAULT_sRGB || 00190 output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) 00191 { 00192 /* If there is no sRGB support this just sets the gamma to the standard 00193 * sRGB value. (This is a side effect of using this function!) 00194 */ 00195 # ifdef PNG_READ_sRGB_SUPPORTED 00196 png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; 00197 # endif 00198 if (is_screen) 00199 output_gamma = PNG_GAMMA_sRGB; 00200 else 00201 output_gamma = PNG_GAMMA_sRGB_INVERSE; 00202 } 00203 00204 else if (output_gamma == PNG_GAMMA_MAC_18 || 00205 output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) 00206 { 00207 if (is_screen) 00208 output_gamma = PNG_GAMMA_MAC_OLD; 00209 else 00210 output_gamma = PNG_GAMMA_MAC_INVERSE; 00211 } 00212 00213 return output_gamma; 00214 } 00215 00216 # ifdef PNG_FLOATING_POINT_SUPPORTED 00217 static png_fixed_point 00218 convert_gamma_value(png_structp png_ptr, double output_gamma) 00219 { 00220 /* The following silently ignores cases where fixed point (times 100,000) 00221 * gamma values are passed to the floating point API. This is safe and it 00222 * means the fixed point constants work just fine with the floating point 00223 * API. The alternative would just lead to undetected errors and spurious 00224 * bug reports. Negative values fail inside the _fixed API unless they 00225 * correspond to the flag values. 00226 */ 00227 if (output_gamma > 0 && output_gamma < 128) 00228 output_gamma *= PNG_FP_1; 00229 00230 /* This preserves -1 and -2 exactly: */ 00231 output_gamma = floor(output_gamma + .5); 00232 00233 if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) 00234 png_fixed_error(png_ptr, "gamma value"); 00235 00236 return (png_fixed_point)output_gamma; 00237 } 00238 # endif 00239 #endif /* READ_ALPHA_MODE || READ_GAMMA */ 00240 00241 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 00242 void PNGFAPI 00243 png_set_alpha_mode_fixed(png_structp png_ptr, int mode, 00244 png_fixed_point output_gamma) 00245 { 00246 int compose = 0; 00247 png_fixed_point file_gamma; 00248 00249 png_debug(1, "in png_set_alpha_mode"); 00250 00251 if (png_ptr == NULL) 00252 return; 00253 00254 output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); 00255 00256 /* Validate the value to ensure it is in a reasonable range. The value 00257 * is expected to be 1 or greater, but this range test allows for some 00258 * viewing correction values. The intent is to weed out users of this API 00259 * who use the inverse of the gamma value accidentally! Since some of these 00260 * values are reasonable this may have to be changed. 00261 */ 00262 if (output_gamma < 70000 || output_gamma > 300000) 00263 png_error(png_ptr, "output gamma out of expected range"); 00264 00265 /* The default file gamma is the inverse of the output gamma; the output 00266 * gamma may be changed below so get the file value first: 00267 */ 00268 file_gamma = png_reciprocal(output_gamma); 00269 00270 /* There are really 8 possibilities here, composed of any combination 00271 * of: 00272 * 00273 * premultiply the color channels 00274 * do not encode non-opaque pixels 00275 * encode the alpha as well as the color channels 00276 * 00277 * The differences disappear if the input/output ('screen') gamma is 1.0, 00278 * because then the encoding is a no-op and there is only the choice of 00279 * premultiplying the color channels or not. 00280 * 00281 * png_set_alpha_mode and png_set_background interact because both use 00282 * png_compose to do the work. Calling both is only useful when 00283 * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along 00284 * with a default gamma value. Otherwise PNG_COMPOSE must not be set. 00285 */ 00286 switch (mode) 00287 { 00288 case PNG_ALPHA_PNG: /* default: png standard */ 00289 /* No compose, but it may be set by png_set_background! */ 00290 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 00291 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 00292 break; 00293 00294 case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ 00295 compose = 1; 00296 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 00297 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 00298 /* The output is linear: */ 00299 output_gamma = PNG_FP_1; 00300 break; 00301 00302 case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ 00303 compose = 1; 00304 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 00305 png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; 00306 /* output_gamma records the encoding of opaque pixels! */ 00307 break; 00308 00309 case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ 00310 compose = 1; 00311 png_ptr->transformations |= PNG_ENCODE_ALPHA; 00312 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 00313 break; 00314 00315 default: 00316 png_error(png_ptr, "invalid alpha mode"); 00317 } 00318 00319 /* Only set the default gamma if the file gamma has not been set (this has 00320 * the side effect that the gamma in a second call to png_set_alpha_mode will 00321 * be ignored.) 00322 */ 00323 if (png_ptr->gamma == 0) 00324 png_ptr->gamma = file_gamma; 00325 00326 /* But always set the output gamma: */ 00327 png_ptr->screen_gamma = output_gamma; 00328 00329 /* Finally, if pre-multiplying, set the background fields to achieve the 00330 * desired result. 00331 */ 00332 if (compose) 00333 { 00334 /* And obtain alpha pre-multiplication by composing on black: */ 00335 png_memset(&png_ptr->background, 0, sizeof png_ptr->background); 00336 png_ptr->background_gamma = png_ptr->gamma; /* just in case */ 00337 png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; 00338 png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; 00339 00340 if (png_ptr->transformations & PNG_COMPOSE) 00341 png_error(png_ptr, 00342 "conflicting calls to set alpha mode and background"); 00343 00344 png_ptr->transformations |= PNG_COMPOSE; 00345 } 00346 00347 /* New API, make sure apps call the correct initializers: */ 00348 png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; 00349 } 00350 00351 # ifdef PNG_FLOATING_POINT_SUPPORTED 00352 void PNGAPI 00353 png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) 00354 { 00355 png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, 00356 output_gamma)); 00357 } 00358 # endif 00359 #endif 00360 00361 #ifdef PNG_READ_QUANTIZE_SUPPORTED 00362 /* Dither file to 8-bit. Supply a palette, the current number 00363 * of elements in the palette, the maximum number of elements 00364 * allowed, and a histogram if possible. If the current number 00365 * of colors is greater then the maximum number, the palette will be 00366 * modified to fit in the maximum number. "full_quantize" indicates 00367 * whether we need a quantizing cube set up for RGB images, or if we 00368 * simply are reducing the number of colors in a paletted image. 00369 */ 00370 00371 typedef struct png_dsort_struct 00372 { 00373 struct png_dsort_struct FAR * next; 00374 png_byte left; 00375 png_byte right; 00376 } png_dsort; 00377 typedef png_dsort FAR * png_dsortp; 00378 typedef png_dsort FAR * FAR * png_dsortpp; 00379 00380 void PNGAPI 00381 png_set_quantize(png_structp png_ptr, png_colorp palette, 00382 int num_palette, int maximum_colors, png_const_uint_16p histogram, 00383 int full_quantize) 00384 { 00385 png_debug(1, "in png_set_quantize"); 00386 00387 if (png_ptr == NULL) 00388 return; 00389 00390 png_ptr->transformations |= PNG_QUANTIZE; 00391 00392 if (!full_quantize) 00393 { 00394 int i; 00395 00396 png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, 00397 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00398 for (i = 0; i < num_palette; i++) 00399 png_ptr->quantize_index[i] = (png_byte)i; 00400 } 00401 00402 if (num_palette > maximum_colors) 00403 { 00404 if (histogram != NULL) 00405 { 00406 /* This is easy enough, just throw out the least used colors. 00407 * Perhaps not the best solution, but good enough. 00408 */ 00409 00410 int i; 00411 00412 /* Initialize an array to sort colors */ 00413 png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, 00414 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00415 00416 /* Initialize the quantize_sort array */ 00417 for (i = 0; i < num_palette; i++) 00418 png_ptr->quantize_sort[i] = (png_byte)i; 00419 00420 /* Find the least used palette entries by starting a 00421 * bubble sort, and running it until we have sorted 00422 * out enough colors. Note that we don't care about 00423 * sorting all the colors, just finding which are 00424 * least used. 00425 */ 00426 00427 for (i = num_palette - 1; i >= maximum_colors; i--) 00428 { 00429 int done; /* To stop early if the list is pre-sorted */ 00430 int j; 00431 00432 done = 1; 00433 for (j = 0; j < i; j++) 00434 { 00435 if (histogram[png_ptr->quantize_sort[j]] 00436 < histogram[png_ptr->quantize_sort[j + 1]]) 00437 { 00438 png_byte t; 00439 00440 t = png_ptr->quantize_sort[j]; 00441 png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; 00442 png_ptr->quantize_sort[j + 1] = t; 00443 done = 0; 00444 } 00445 } 00446 00447 if (done) 00448 break; 00449 } 00450 00451 /* Swap the palette around, and set up a table, if necessary */ 00452 if (full_quantize) 00453 { 00454 int j = num_palette; 00455 00456 /* Put all the useful colors within the max, but don't 00457 * move the others. 00458 */ 00459 for (i = 0; i < maximum_colors; i++) 00460 { 00461 if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 00462 { 00463 do 00464 j--; 00465 while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 00466 00467 palette[i] = palette[j]; 00468 } 00469 } 00470 } 00471 else 00472 { 00473 int j = num_palette; 00474 00475 /* Move all the used colors inside the max limit, and 00476 * develop a translation table. 00477 */ 00478 for (i = 0; i < maximum_colors; i++) 00479 { 00480 /* Only move the colors we need to */ 00481 if ((int)png_ptr->quantize_sort[i] >= maximum_colors) 00482 { 00483 png_color tmp_color; 00484 00485 do 00486 j--; 00487 while ((int)png_ptr->quantize_sort[j] >= maximum_colors); 00488 00489 tmp_color = palette[j]; 00490 palette[j] = palette[i]; 00491 palette[i] = tmp_color; 00492 /* Indicate where the color went */ 00493 png_ptr->quantize_index[j] = (png_byte)i; 00494 png_ptr->quantize_index[i] = (png_byte)j; 00495 } 00496 } 00497 00498 /* Find closest color for those colors we are not using */ 00499 for (i = 0; i < num_palette; i++) 00500 { 00501 if ((int)png_ptr->quantize_index[i] >= maximum_colors) 00502 { 00503 int min_d, k, min_k, d_index; 00504 00505 /* Find the closest color to one we threw out */ 00506 d_index = png_ptr->quantize_index[i]; 00507 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 00508 for (k = 1, min_k = 0; k < maximum_colors; k++) 00509 { 00510 int d; 00511 00512 d = PNG_COLOR_DIST(palette[d_index], palette[k]); 00513 00514 if (d < min_d) 00515 { 00516 min_d = d; 00517 min_k = k; 00518 } 00519 } 00520 /* Point to closest color */ 00521 png_ptr->quantize_index[i] = (png_byte)min_k; 00522 } 00523 } 00524 } 00525 png_free(png_ptr, png_ptr->quantize_sort); 00526 png_ptr->quantize_sort = NULL; 00527 } 00528 else 00529 { 00530 /* This is much harder to do simply (and quickly). Perhaps 00531 * we need to go through a median cut routine, but those 00532 * don't always behave themselves with only a few colors 00533 * as input. So we will just find the closest two colors, 00534 * and throw out one of them (chosen somewhat randomly). 00535 * [We don't understand this at all, so if someone wants to 00536 * work on improving it, be our guest - AED, GRP] 00537 */ 00538 int i; 00539 int max_d; 00540 int num_new_palette; 00541 png_dsortp t; 00542 png_dsortpp hash; 00543 00544 t = NULL; 00545 00546 /* Initialize palette index arrays */ 00547 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 00548 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00549 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 00550 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00551 00552 /* Initialize the sort array */ 00553 for (i = 0; i < num_palette; i++) 00554 { 00555 png_ptr->index_to_palette[i] = (png_byte)i; 00556 png_ptr->palette_to_index[i] = (png_byte)i; 00557 } 00558 00559 hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * 00560 png_sizeof(png_dsortp))); 00561 00562 num_new_palette = num_palette; 00563 00564 /* Initial wild guess at how far apart the farthest pixel 00565 * pair we will be eliminating will be. Larger 00566 * numbers mean more areas will be allocated, Smaller 00567 * numbers run the risk of not saving enough data, and 00568 * having to do this all over again. 00569 * 00570 * I have not done extensive checking on this number. 00571 */ 00572 max_d = 96; 00573 00574 while (num_new_palette > maximum_colors) 00575 { 00576 for (i = 0; i < num_new_palette - 1; i++) 00577 { 00578 int j; 00579 00580 for (j = i + 1; j < num_new_palette; j++) 00581 { 00582 int d; 00583 00584 d = PNG_COLOR_DIST(palette[i], palette[j]); 00585 00586 if (d <= max_d) 00587 { 00588 00589 t = (png_dsortp)png_malloc_warn(png_ptr, 00590 (png_uint_32)(png_sizeof(png_dsort))); 00591 00592 if (t == NULL) 00593 break; 00594 00595 t->next = hash[d]; 00596 t->left = (png_byte)i; 00597 t->right = (png_byte)j; 00598 hash[d] = t; 00599 } 00600 } 00601 if (t == NULL) 00602 break; 00603 } 00604 00605 if (t != NULL) 00606 for (i = 0; i <= max_d; i++) 00607 { 00608 if (hash[i] != NULL) 00609 { 00610 png_dsortp p; 00611 00612 for (p = hash[i]; p; p = p->next) 00613 { 00614 if ((int)png_ptr->index_to_palette[p->left] 00615 < num_new_palette && 00616 (int)png_ptr->index_to_palette[p->right] 00617 < num_new_palette) 00618 { 00619 int j, next_j; 00620 00621 if (num_new_palette & 0x01) 00622 { 00623 j = p->left; 00624 next_j = p->right; 00625 } 00626 else 00627 { 00628 j = p->right; 00629 next_j = p->left; 00630 } 00631 00632 num_new_palette--; 00633 palette[png_ptr->index_to_palette[j]] 00634 = palette[num_new_palette]; 00635 if (!full_quantize) 00636 { 00637 int k; 00638 00639 for (k = 0; k < num_palette; k++) 00640 { 00641 if (png_ptr->quantize_index[k] == 00642 png_ptr->index_to_palette[j]) 00643 png_ptr->quantize_index[k] = 00644 png_ptr->index_to_palette[next_j]; 00645 00646 if ((int)png_ptr->quantize_index[k] == 00647 num_new_palette) 00648 png_ptr->quantize_index[k] = 00649 png_ptr->index_to_palette[j]; 00650 } 00651 } 00652 00653 png_ptr->index_to_palette[png_ptr->palette_to_index 00654 [num_new_palette]] = png_ptr->index_to_palette[j]; 00655 00656 png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 00657 = png_ptr->palette_to_index[num_new_palette]; 00658 00659 png_ptr->index_to_palette[j] = 00660 (png_byte)num_new_palette; 00661 00662 png_ptr->palette_to_index[num_new_palette] = 00663 (png_byte)j; 00664 } 00665 if (num_new_palette <= maximum_colors) 00666 break; 00667 } 00668 if (num_new_palette <= maximum_colors) 00669 break; 00670 } 00671 } 00672 00673 for (i = 0; i < 769; i++) 00674 { 00675 if (hash[i] != NULL) 00676 { 00677 png_dsortp p = hash[i]; 00678 while (p) 00679 { 00680 t = p->next; 00681 png_free(png_ptr, p); 00682 p = t; 00683 } 00684 } 00685 hash[i] = 0; 00686 } 00687 max_d += 96; 00688 } 00689 png_free(png_ptr, hash); 00690 png_free(png_ptr, png_ptr->palette_to_index); 00691 png_free(png_ptr, png_ptr->index_to_palette); 00692 png_ptr->palette_to_index = NULL; 00693 png_ptr->index_to_palette = NULL; 00694 } 00695 num_palette = maximum_colors; 00696 } 00697 if (png_ptr->palette == NULL) 00698 { 00699 png_ptr->palette = palette; 00700 } 00701 png_ptr->num_palette = (png_uint_16)num_palette; 00702 00703 if (full_quantize) 00704 { 00705 int i; 00706 png_bytep distance; 00707 int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + 00708 PNG_QUANTIZE_BLUE_BITS; 00709 int num_red = (1 << PNG_QUANTIZE_RED_BITS); 00710 int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); 00711 int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); 00712 png_size_t num_entries = ((png_size_t)1 << total_bits); 00713 00714 png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, 00715 (png_uint_32)(num_entries * png_sizeof(png_byte))); 00716 00717 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 00718 png_sizeof(png_byte))); 00719 00720 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); 00721 00722 for (i = 0; i < num_palette; i++) 00723 { 00724 int ir, ig, ib; 00725 int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); 00726 int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); 00727 int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); 00728 00729 for (ir = 0; ir < num_red; ir++) 00730 { 00731 /* int dr = abs(ir - r); */ 00732 int dr = ((ir > r) ? ir - r : r - ir); 00733 int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + 00734 PNG_QUANTIZE_GREEN_BITS)); 00735 00736 for (ig = 0; ig < num_green; ig++) 00737 { 00738 /* int dg = abs(ig - g); */ 00739 int dg = ((ig > g) ? ig - g : g - ig); 00740 int dt = dr + dg; 00741 int dm = ((dr > dg) ? dr : dg); 00742 int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); 00743 00744 for (ib = 0; ib < num_blue; ib++) 00745 { 00746 int d_index = index_g | ib; 00747 /* int db = abs(ib - b); */ 00748 int db = ((ib > b) ? ib - b : b - ib); 00749 int dmax = ((dm > db) ? dm : db); 00750 int d = dmax + dt + db; 00751 00752 if (d < (int)distance[d_index]) 00753 { 00754 distance[d_index] = (png_byte)d; 00755 png_ptr->palette_lookup[d_index] = (png_byte)i; 00756 } 00757 } 00758 } 00759 } 00760 } 00761 00762 png_free(png_ptr, distance); 00763 } 00764 } 00765 #endif /* PNG_READ_QUANTIZE_SUPPORTED */ 00766 00767 #ifdef PNG_READ_GAMMA_SUPPORTED 00768 void PNGFAPI 00769 png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, 00770 png_fixed_point file_gamma) 00771 { 00772 png_debug(1, "in png_set_gamma_fixed"); 00773 00774 if (png_ptr == NULL) 00775 return; 00776 00777 /* New in libpng-1.5.4 - reserve particular negative values as flags. */ 00778 scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); 00779 file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); 00780 00781 #if PNG_LIBPNG_VER >= 10600 00782 /* Checking the gamma values for being >0 was added in 1.5.4 along with the 00783 * premultiplied alpha support; this actually hides an undocumented feature 00784 * of the previous implementation which allowed gamma processing to be 00785 * disabled in background handling. There is no evidence (so far) that this 00786 * was being used; however, png_set_background itself accepted and must still 00787 * accept '0' for the gamma value it takes, because it isn't always used. 00788 * 00789 * Since this is an API change (albeit a very minor one that removes an 00790 * undocumented API feature) it will not be made until libpng-1.6.0. 00791 */ 00792 if (file_gamma <= 0) 00793 png_error(png_ptr, "invalid file gamma in png_set_gamma"); 00794 00795 if (scrn_gamma <= 0) 00796 png_error(png_ptr, "invalid screen gamma in png_set_gamma"); 00797 #endif 00798 00799 /* Set the gamma values unconditionally - this overrides the value in the PNG 00800 * file if a gAMA chunk was present. png_set_alpha_mode provides a 00801 * different, easier, way to default the file gamma. 00802 */ 00803 png_ptr->gamma = file_gamma; 00804 png_ptr->screen_gamma = scrn_gamma; 00805 } 00806 00807 # ifdef PNG_FLOATING_POINT_SUPPORTED 00808 void PNGAPI 00809 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) 00810 { 00811 png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), 00812 convert_gamma_value(png_ptr, file_gamma)); 00813 } 00814 # endif /* FLOATING_POINT_SUPPORTED */ 00815 #endif /* READ_GAMMA */ 00816 00817 #ifdef PNG_READ_EXPAND_SUPPORTED 00818 /* Expand paletted images to RGB, expand grayscale images of 00819 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 00820 * to alpha channels. 00821 */ 00822 void PNGAPI 00823 png_set_expand(png_structp png_ptr) 00824 { 00825 png_debug(1, "in png_set_expand"); 00826 00827 if (png_ptr == NULL) 00828 return; 00829 00830 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00831 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00832 } 00833 00834 /* GRR 19990627: the following three functions currently are identical 00835 * to png_set_expand(). However, it is entirely reasonable that someone 00836 * might wish to expand an indexed image to RGB but *not* expand a single, 00837 * fully transparent palette entry to a full alpha channel--perhaps instead 00838 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 00839 * the transparent color with a particular RGB value, or drop tRNS entirely. 00840 * IOW, a future version of the library may make the transformations flag 00841 * a bit more fine-grained, with separate bits for each of these three 00842 * functions. 00843 * 00844 * More to the point, these functions make it obvious what libpng will be 00845 * doing, whereas "expand" can (and does) mean any number of things. 00846 * 00847 * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified 00848 * to expand only the sample depth but not to expand the tRNS to alpha 00849 * and its name was changed to png_set_expand_gray_1_2_4_to_8(). 00850 */ 00851 00852 /* Expand paletted images to RGB. */ 00853 void PNGAPI 00854 png_set_palette_to_rgb(png_structp png_ptr) 00855 { 00856 png_debug(1, "in png_set_palette_to_rgb"); 00857 00858 if (png_ptr == NULL) 00859 return; 00860 00861 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00862 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00863 } 00864 00865 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 00866 void PNGAPI 00867 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) 00868 { 00869 png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); 00870 00871 if (png_ptr == NULL) 00872 return; 00873 00874 png_ptr->transformations |= PNG_EXPAND; 00875 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00876 } 00877 00878 00879 00880 /* Expand tRNS chunks to alpha channels. */ 00881 void PNGAPI 00882 png_set_tRNS_to_alpha(png_structp png_ptr) 00883 { 00884 png_debug(1, "in png_set_tRNS_to_alpha"); 00885 00886 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00887 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00888 } 00889 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ 00890 00891 #ifdef PNG_READ_EXPAND_16_SUPPORTED 00892 /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise 00893 * it may not work correctly.) 00894 */ 00895 void PNGAPI 00896 png_set_expand_16(png_structp png_ptr) 00897 { 00898 png_debug(1, "in png_set_expand_16"); 00899 00900 if (png_ptr == NULL) 00901 return; 00902 00903 png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); 00904 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00905 00906 /* New API, make sure apps call the correct initializers: */ 00907 png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; 00908 } 00909 #endif 00910 00911 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 00912 void PNGAPI 00913 png_set_gray_to_rgb(png_structp png_ptr) 00914 { 00915 png_debug(1, "in png_set_gray_to_rgb"); 00916 00917 if (png_ptr != NULL) 00918 { 00919 /* Because rgb must be 8 bits or more: */ 00920 png_set_expand_gray_1_2_4_to_8(png_ptr); 00921 png_ptr->transformations |= PNG_GRAY_TO_RGB; 00922 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00923 } 00924 } 00925 #endif 00926 00927 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 00928 void PNGFAPI 00929 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, 00930 png_fixed_point red, png_fixed_point green) 00931 { 00932 png_debug(1, "in png_set_rgb_to_gray"); 00933 00934 if (png_ptr == NULL) 00935 return; 00936 00937 switch(error_action) 00938 { 00939 case PNG_ERROR_ACTION_NONE: 00940 png_ptr->transformations |= PNG_RGB_TO_GRAY; 00941 break; 00942 00943 case PNG_ERROR_ACTION_WARN: 00944 png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 00945 break; 00946 00947 case PNG_ERROR_ACTION_ERROR: 00948 png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 00949 break; 00950 00951 default: 00952 png_error(png_ptr, "invalid error action to rgb_to_gray"); 00953 break; 00954 } 00955 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 00956 #ifdef PNG_READ_EXPAND_SUPPORTED 00957 png_ptr->transformations |= PNG_EXPAND; 00958 #else 00959 { 00960 png_warning(png_ptr, 00961 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); 00962 00963 png_ptr->transformations &= ~PNG_RGB_TO_GRAY; 00964 } 00965 #endif 00966 { 00967 if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) 00968 { 00969 png_uint_16 red_int, green_int; 00970 00971 /* NOTE: this calculation does not round, but this behavior is retained 00972 * for consistency, the inaccuracy is very small. The code here always 00973 * overwrites the coefficients, regardless of whether they have been 00974 * defaulted or set already. 00975 */ 00976 red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); 00977 green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); 00978 00979 png_ptr->rgb_to_gray_red_coeff = red_int; 00980 png_ptr->rgb_to_gray_green_coeff = green_int; 00981 png_ptr->rgb_to_gray_coefficients_set = 1; 00982 } 00983 00984 else 00985 { 00986 if (red >= 0 && green >= 0) 00987 png_warning(png_ptr, 00988 "ignoring out of range rgb_to_gray coefficients"); 00989 00990 /* Use the defaults, from the cHRM chunk if set, else the historical 00991 * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See 00992 * png_do_rgb_to_gray for more discussion of the values. In this case 00993 * the coefficients are not marked as 'set' and are not overwritten if 00994 * something has already provided a default. 00995 */ 00996 if (png_ptr->rgb_to_gray_red_coeff == 0 && 00997 png_ptr->rgb_to_gray_green_coeff == 0) 00998 { 00999 png_ptr->rgb_to_gray_red_coeff = 6968; 01000 png_ptr->rgb_to_gray_green_coeff = 23434; 01001 /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ 01002 } 01003 } 01004 } 01005 } 01006 01007 #ifdef PNG_FLOATING_POINT_SUPPORTED 01008 /* Convert a RGB image to a grayscale of the same width. This allows us, 01009 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 01010 */ 01011 01012 void PNGAPI 01013 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, 01014 double green) 01015 { 01016 if (png_ptr == NULL) 01017 return; 01018 01019 png_set_rgb_to_gray_fixed(png_ptr, error_action, 01020 png_fixed(png_ptr, red, "rgb to gray red coefficient"), 01021 png_fixed(png_ptr, green, "rgb to gray green coefficient")); 01022 } 01023 #endif /* FLOATING POINT */ 01024 01025 #endif 01026 01027 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 01028 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 01029 void PNGAPI 01030 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr 01031 read_user_transform_fn) 01032 { 01033 png_debug(1, "in png_set_read_user_transform_fn"); 01034 01035 if (png_ptr == NULL) 01036 return; 01037 01038 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 01039 png_ptr->transformations |= PNG_USER_TRANSFORM; 01040 png_ptr->read_user_transform_fn = read_user_transform_fn; 01041 #endif 01042 } 01043 #endif 01044 01045 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 01046 #ifdef PNG_READ_GAMMA_SUPPORTED 01047 /* In the case of gamma transformations only do transformations on images where 01048 * the [file] gamma and screen_gamma are not close reciprocals, otherwise it 01049 * slows things down slightly, and also needlessly introduces small errors. 01050 */ 01051 static int /* PRIVATE */ 01052 png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) 01053 { 01054 /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma 01055 * correction as a difference of the overall transform from 1.0 01056 * 01057 * We want to compare the threshold with s*f - 1, if we get 01058 * overflow here it is because of wacky gamma values so we 01059 * turn on processing anyway. 01060 */ 01061 png_fixed_point gtest; 01062 return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || 01063 png_gamma_significant(gtest); 01064 } 01065 #endif 01066 01067 /* Initialize everything needed for the read. This includes modifying 01068 * the palette. 01069 */ 01070 01071 /*For the moment 'png_init_palette_transformations' and 01072 * 'png_init_rgb_transformations' only do some flag canceling optimizations. 01073 * The intent is that these two routines should have palette or rgb operations 01074 * extracted from 'png_init_read_transformations'. 01075 */ 01076 static void /* PRIVATE */ 01077 png_init_palette_transformations(png_structp png_ptr) 01078 { 01079 /* Called to handle the (input) palette case. In png_do_read_transformations 01080 * the first step is to expand the palette if requested, so this code must 01081 * take care to only make changes that are invariant with respect to the 01082 * palette expansion, or only do them if there is no expansion. 01083 * 01084 * STRIP_ALPHA has already been handled in the caller (by setting num_trans 01085 * to 0.) 01086 */ 01087 int input_has_alpha = 0; 01088 int input_has_transparency = 0; 01089 01090 if (png_ptr->num_trans > 0) 01091 { 01092 int i; 01093 01094 /* Ignore if all the entries are opaque (unlikely!) */ 01095 for (i=0; i<png_ptr->num_trans; ++i) 01096 if (png_ptr->trans_alpha[i] == 255) 01097 continue; 01098 else if (png_ptr->trans_alpha[i] == 0) 01099 input_has_transparency = 1; 01100 else 01101 input_has_alpha = 1; 01102 } 01103 01104 /* If no alpha we can optimize. */ 01105 if (!input_has_alpha) 01106 { 01107 /* Any alpha means background and associative alpha processing is 01108 * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA 01109 * and ENCODE_ALPHA are irrelevant. 01110 */ 01111 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 01112 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 01113 01114 if (!input_has_transparency) 01115 png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 01116 } 01117 01118 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 01119 /* png_set_background handling - deals with the complexity of whether the 01120 * background color is in the file format or the screen format in the case 01121 * where an 'expand' will happen. 01122 */ 01123 01124 /* The following code cannot be entered in the alpha pre-multiplication case 01125 * because PNG_BACKGROUND_EXPAND is cancelled below. 01126 */ 01127 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 01128 (png_ptr->transformations & PNG_EXPAND)) 01129 { 01130 { 01131 png_ptr->background.red = 01132 png_ptr->palette[png_ptr->background.index].red; 01133 png_ptr->background.green = 01134 png_ptr->palette[png_ptr->background.index].green; 01135 png_ptr->background.blue = 01136 png_ptr->palette[png_ptr->background.index].blue; 01137 01138 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 01139 if (png_ptr->transformations & PNG_INVERT_ALPHA) 01140 { 01141 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 01142 { 01143 /* Invert the alpha channel (in tRNS) unless the pixels are 01144 * going to be expanded, in which case leave it for later 01145 */ 01146 int i, istop = png_ptr->num_trans; 01147 01148 for (i=0; i<istop; i++) 01149 png_ptr->trans_alpha[i] = (png_byte)(255 - 01150 png_ptr->trans_alpha[i]); 01151 } 01152 } 01153 #endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ 01154 } 01155 } /* background expand and (therefore) no alpha association. */ 01156 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ 01157 } 01158 01159 static void /* PRIVATE */ 01160 png_init_rgb_transformations(png_structp png_ptr) 01161 { 01162 /* Added to libpng-1.5.4: check the color type to determine whether there 01163 * is any alpha or transparency in the image and simply cancel the 01164 * background and alpha mode stuff if there isn't. 01165 */ 01166 int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; 01167 int input_has_transparency = png_ptr->num_trans > 0; 01168 01169 /* If no alpha we can optimize. */ 01170 if (!input_has_alpha) 01171 { 01172 /* Any alpha means background and associative alpha processing is 01173 * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA 01174 * and ENCODE_ALPHA are irrelevant. 01175 */ 01176 # ifdef PNG_READ_ALPHA_MODE_SUPPORTED 01177 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 01178 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 01179 # endif 01180 01181 if (!input_has_transparency) 01182 png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); 01183 } 01184 01185 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 01186 /* png_set_background handling - deals with the complexity of whether the 01187 * background color is in the file format or the screen format in the case 01188 * where an 'expand' will happen. 01189 */ 01190 01191 /* The following code cannot be entered in the alpha pre-multiplication case 01192 * because PNG_BACKGROUND_EXPAND is cancelled below. 01193 */ 01194 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 01195 (png_ptr->transformations & PNG_EXPAND) && 01196 !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) 01197 /* i.e., GRAY or GRAY_ALPHA */ 01198 { 01199 { 01200 /* Expand background and tRNS chunks */ 01201 int gray = png_ptr->background.gray; 01202 int trans_gray = png_ptr->trans_color.gray; 01203 01204 switch (png_ptr->bit_depth) 01205 { 01206 case 1: 01207 gray *= 0xff; 01208 trans_gray *= 0xff; 01209 break; 01210 01211 case 2: 01212 gray *= 0x55; 01213 trans_gray *= 0x55; 01214 break; 01215 01216 case 4: 01217 gray *= 0x11; 01218 trans_gray *= 0x11; 01219 break; 01220 01221 default: 01222 01223 case 8: 01224 /* Already 8 bits, fall through */ 01225 01226 case 16: 01227 /* Already a full 16 bits */ 01228 break; 01229 } 01230 01231 png_ptr->background.red = png_ptr->background.green = 01232 png_ptr->background.blue = (png_uint_16)gray; 01233 01234 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 01235 { 01236 png_ptr->trans_color.red = png_ptr->trans_color.green = 01237 png_ptr->trans_color.blue = (png_uint_16)trans_gray; 01238 } 01239 } 01240 } /* background expand and (therefore) no alpha association. */ 01241 #endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ 01242 } 01243 01244 void /* PRIVATE */ 01245 png_init_read_transformations(png_structp png_ptr) 01246 { 01247 png_debug(1, "in png_init_read_transformations"); 01248 01249 /* This internal function is called from png_read_start_row in pngrutil.c 01250 * and it is called before the 'rowbytes' calculation is done, so the code 01251 * in here can change or update the transformations flags. 01252 * 01253 * First do updates that do not depend on the details of the PNG image data 01254 * being processed. 01255 */ 01256 01257 #ifdef PNG_READ_GAMMA_SUPPORTED 01258 /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds 01259 * png_set_alpha_mode and this is another source for a default file gamma so 01260 * the test needs to be performed later - here. In addition prior to 1.5.4 01261 * the tests were repeated for the PALETTE color type here - this is no 01262 * longer necessary (and doesn't seem to have been necessary before.) 01263 */ 01264 { 01265 /* The following temporary indicates if overall gamma correction is 01266 * required. 01267 */ 01268 int gamma_correction = 0; 01269 01270 if (png_ptr->gamma != 0) /* has been set */ 01271 { 01272 if (png_ptr->screen_gamma != 0) /* screen set too */ 01273 gamma_correction = png_gamma_threshold(png_ptr->gamma, 01274 png_ptr->screen_gamma); 01275 01276 else 01277 /* Assume the output matches the input; a long time default behavior 01278 * of libpng, although the standard has nothing to say about this. 01279 */ 01280 png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma); 01281 } 01282 01283 else if (png_ptr->screen_gamma != 0) 01284 /* The converse - assume the file matches the screen, note that this 01285 * perhaps undesireable default can (from 1.5.4) be changed by calling 01286 * png_set_alpha_mode (even if the alpha handling mode isn't required 01287 * or isn't changed from the default.) 01288 */ 01289 png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma); 01290 01291 else /* neither are set */ 01292 /* Just in case the following prevents any processing - file and screen 01293 * are both assumed to be linear and there is no way to introduce a 01294 * third gamma value other than png_set_background with 'UNIQUE', and, 01295 * prior to 1.5.4 01296 */ 01297 png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1; 01298 01299 /* Now turn the gamma transformation on or off as appropriate. Notice 01300 * that PNG_GAMMA just refers to the file->screen correction. Alpha 01301 * composition may independently cause gamma correction because it needs 01302 * linear data (e.g. if the file has a gAMA chunk but the screen gamma 01303 * hasn't been specified.) In any case this flag may get turned off in 01304 * the code immediately below if the transform can be handled outside the 01305 * row loop. 01306 */ 01307 if (gamma_correction) 01308 png_ptr->transformations |= PNG_GAMMA; 01309 01310 else 01311 png_ptr->transformations &= ~PNG_GAMMA; 01312 } 01313 #endif 01314 01315 /* Certain transformations have the effect of preventing other 01316 * transformations that happen afterward in png_do_read_transformations, 01317 * resolve the interdependencies here. From the code of 01318 * png_do_read_transformations the order is: 01319 * 01320 * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) 01321 * 2) PNG_STRIP_ALPHA (if no compose) 01322 * 3) PNG_RGB_TO_GRAY 01323 * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY 01324 * 5) PNG_COMPOSE 01325 * 6) PNG_GAMMA 01326 * 7) PNG_STRIP_ALPHA (if compose) 01327 * 8) PNG_ENCODE_ALPHA 01328 * 9) PNG_SCALE_16_TO_8 01329 * 10) PNG_16_TO_8 01330 * 11) PNG_QUANTIZE (converts to palette) 01331 * 12) PNG_EXPAND_16 01332 * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY 01333 * 14) PNG_INVERT_MONO 01334 * 15) PNG_SHIFT 01335 * 16) PNG_PACK 01336 * 17) PNG_BGR 01337 * 18) PNG_PACKSWAP 01338 * 19) PNG_FILLER (includes PNG_ADD_ALPHA) 01339 * 20) PNG_INVERT_ALPHA 01340 * 21) PNG_SWAP_ALPHA 01341 * 22) PNG_SWAP_BYTES 01342 * 23) PNG_USER_TRANSFORM [must be last] 01343 */ 01344 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 01345 if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 01346 !(png_ptr->transformations & PNG_COMPOSE)) 01347 { 01348 /* Stripping the alpha channel happens immediately after the 'expand' 01349 * transformations, before all other transformation, so it cancels out 01350 * the alpha handling. It has the side effect negating the effect of 01351 * PNG_EXPAND_tRNS too: 01352 */ 01353 png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | 01354 PNG_EXPAND_tRNS); 01355 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 01356 01357 /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen 01358 * so transparency information would remain just so long as it wasn't 01359 * expanded. This produces unexpected API changes if the set of things 01360 * that do PNG_EXPAND_tRNS changes (perfectly possible given the 01361 * documentation - which says ask for what you want, accept what you 01362 * get.) This makes the behavior consistent from 1.5.4: 01363 */ 01364 png_ptr->num_trans = 0; 01365 } 01366 #endif /* STRIP_ALPHA supported, no COMPOSE */ 01367 01368 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 01369 /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA 01370 * settings will have no effect. 01371 */ 01372 if (!png_gamma_significant(png_ptr->screen_gamma)) 01373 { 01374 png_ptr->transformations &= ~PNG_ENCODE_ALPHA; 01375 png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; 01376 } 01377 #endif 01378 01379 #if defined(PNG_READ_EXPAND_SUPPORTED) && \ 01380 defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 01381 defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 01382 /* Detect gray background and attempt to enable optimization for 01383 * gray --> RGB case. 01384 * 01385 * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 01386 * RGB_ALPHA (in which case need_expand is superfluous anyway), the 01387 * background color might actually be gray yet not be flagged as such. 01388 * This is not a problem for the current code, which uses 01389 * PNG_BACKGROUND_IS_GRAY only to decide when to do the 01390 * png_do_gray_to_rgb() transformation. 01391 * 01392 * TODO: this code needs to be revised to avoid the complexity and 01393 * interdependencies. The color type of the background should be recorded in 01394 * png_set_background, along with the bit depth, then the code has a record 01395 * of exactly what color space the background is currently in. 01396 */ 01397 if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) 01398 { 01399 /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if 01400 * the file was grayscale the background value is gray. 01401 */ 01402 if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) 01403 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 01404 } 01405 01406 else if (png_ptr->transformations & PNG_COMPOSE) 01407 { 01408 /* PNG_COMPOSE: png_set_background was called with need_expand false, 01409 * so the color is in the color space of the output or png_set_alpha_mode 01410 * was called and the color is black. Ignore RGB_TO_GRAY because that 01411 * happens before GRAY_TO_RGB. 01412 */ 01413 if (png_ptr->transformations & PNG_GRAY_TO_RGB) 01414 { 01415 if (png_ptr->background.red == png_ptr->background.green && 01416 png_ptr->background.red == png_ptr->background.blue) 01417 { 01418 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 01419 png_ptr->background.gray = png_ptr->background.red; 01420 } 01421 } 01422 } 01423 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */ 01424 01425 /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations 01426 * can be performed directly on the palette, and some (such as rgb to gray) 01427 * can be optimized inside the palette. This is particularly true of the 01428 * composite (background and alpha) stuff, which can be pretty much all done 01429 * in the palette even if the result is expanded to RGB or gray afterward. 01430 * 01431 * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and 01432 * earlier and the palette stuff is actually handled on the first row. This 01433 * leads to the reported bug that the palette returned by png_get_PLTE is not 01434 * updated. 01435 */ 01436 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01437 png_init_palette_transformations(png_ptr); 01438 01439 else 01440 png_init_rgb_transformations(png_ptr); 01441 01442 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 01443 defined(PNG_READ_EXPAND_16_SUPPORTED) 01444 if ((png_ptr->transformations & PNG_EXPAND_16) && 01445 (png_ptr->transformations & PNG_COMPOSE) && 01446 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 01447 png_ptr->bit_depth != 16) 01448 { 01449 /* TODO: fix this. Because the expand_16 operation is after the compose 01450 * handling the background color must be 8, not 16, bits deep, but the 01451 * application will supply a 16-bit value so reduce it here. 01452 * 01453 * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at 01454 * present, so that case is ok (until do_expand_16 is moved.) 01455 * 01456 * NOTE: this discards the low 16 bits of the user supplied background 01457 * color, but until expand_16 works properly there is no choice! 01458 */ 01459 # define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) 01460 CHOP(png_ptr->background.red); 01461 CHOP(png_ptr->background.green); 01462 CHOP(png_ptr->background.blue); 01463 CHOP(png_ptr->background.gray); 01464 # undef CHOP 01465 } 01466 #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ 01467 01468 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 01469 (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ 01470 defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) 01471 if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && 01472 (png_ptr->transformations & PNG_COMPOSE) && 01473 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 01474 png_ptr->bit_depth == 16) 01475 { 01476 /* On the other hand, if a 16-bit file is to be reduced to 8-bits per 01477 * component this will also happen after PNG_COMPOSE and so the background 01478 * color must be pre-expanded here. 01479 * 01480 * TODO: fix this too. 01481 */ 01482 png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); 01483 png_ptr->background.green = 01484 (png_uint_16)(png_ptr->background.green * 257); 01485 png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); 01486 png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); 01487 } 01488 #endif 01489 01490 /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the 01491 * background support (see the comments in scripts/pnglibconf.dfa), this 01492 * allows pre-multiplication of the alpha channel to be implemented as 01493 * compositing on black. This is probably sub-optimal and has been done in 01494 * 1.5.4 betas simply to enable external critique and testing (i.e. to 01495 * implement the new API quickly, without lots of internal changes.) 01496 */ 01497 01498 #ifdef PNG_READ_GAMMA_SUPPORTED 01499 # ifdef PNG_READ_BACKGROUND_SUPPORTED 01500 /* Includes ALPHA_MODE */ 01501 png_ptr->background_1 = png_ptr->background; 01502 # endif 01503 01504 /* This needs to change - in the palette image case a whole set of tables are 01505 * built when it would be quicker to just calculate the correct value for 01506 * each palette entry directly. Also, the test is too tricky - why check 01507 * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that 01508 * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the 01509 * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction 01510 * the gamma tables will not be built even if composition is required on a 01511 * gamma encoded value. 01512 * 01513 * In 1.5.4 this is addressed below by an additional check on the individual 01514 * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the 01515 * tables. 01516 */ 01517 if ((png_ptr->transformations & PNG_GAMMA) 01518 || ((png_ptr->transformations & PNG_RGB_TO_GRAY) 01519 && (png_gamma_significant(png_ptr->gamma) || 01520 png_gamma_significant(png_ptr->screen_gamma))) 01521 || ((png_ptr->transformations & PNG_COMPOSE) 01522 && (png_gamma_significant(png_ptr->gamma) 01523 || png_gamma_significant(png_ptr->screen_gamma) 01524 # ifdef PNG_READ_BACKGROUND_SUPPORTED 01525 || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE 01526 && png_gamma_significant(png_ptr->background_gamma)) 01527 # endif 01528 )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) 01529 && png_gamma_significant(png_ptr->screen_gamma)) 01530 ) 01531 { 01532 png_build_gamma_table(png_ptr, png_ptr->bit_depth); 01533 01534 #ifdef PNG_READ_BACKGROUND_SUPPORTED 01535 if (png_ptr->transformations & PNG_COMPOSE) 01536 { 01537 /* Issue a warning about this combination: because RGB_TO_GRAY is 01538 * optimized to do the gamma transform if present yet do_background has 01539 * to do the same thing if both options are set a 01540 * double-gamma-correction happens. This is true in all versions of 01541 * libpng to date. 01542 */ 01543 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 01544 png_warning(png_ptr, 01545 "libpng does not support gamma+background+rgb_to_gray"); 01546 01547 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01548 { 01549 /* We don't get to here unless there is a tRNS chunk with non-opaque 01550 * entries - see the checking code at the start of this function. 01551 */ 01552 png_color back, back_1; 01553 png_colorp palette = png_ptr->palette; 01554 int num_palette = png_ptr->num_palette; 01555 int i; 01556 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 01557 { 01558 01559 back.red = png_ptr->gamma_table[png_ptr->background.red]; 01560 back.green = png_ptr->gamma_table[png_ptr->background.green]; 01561 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 01562 01563 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 01564 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 01565 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 01566 } 01567 else 01568 { 01569 png_fixed_point g, gs; 01570 01571 switch (png_ptr->background_gamma_type) 01572 { 01573 case PNG_BACKGROUND_GAMMA_SCREEN: 01574 g = (png_ptr->screen_gamma); 01575 gs = PNG_FP_1; 01576 break; 01577 01578 case PNG_BACKGROUND_GAMMA_FILE: 01579 g = png_reciprocal(png_ptr->gamma); 01580 gs = png_reciprocal2(png_ptr->gamma, 01581 png_ptr->screen_gamma); 01582 break; 01583 01584 case PNG_BACKGROUND_GAMMA_UNIQUE: 01585 g = png_reciprocal(png_ptr->background_gamma); 01586 gs = png_reciprocal2(png_ptr->background_gamma, 01587 png_ptr->screen_gamma); 01588 break; 01589 default: 01590 g = PNG_FP_1; /* back_1 */ 01591 gs = PNG_FP_1; /* back */ 01592 break; 01593 } 01594 01595 if (png_gamma_significant(gs)) 01596 { 01597 back.red = png_gamma_8bit_correct(png_ptr->background.red, 01598 gs); 01599 back.green = png_gamma_8bit_correct(png_ptr->background.green, 01600 gs); 01601 back.blue = png_gamma_8bit_correct(png_ptr->background.blue, 01602 gs); 01603 } 01604 01605 else 01606 { 01607 back.red = (png_byte)png_ptr->background.red; 01608 back.green = (png_byte)png_ptr->background.green; 01609 back.blue = (png_byte)png_ptr->background.blue; 01610 } 01611 01612 if (png_gamma_significant(g)) 01613 { 01614 back_1.red = png_gamma_8bit_correct(png_ptr->background.red, 01615 g); 01616 back_1.green = png_gamma_8bit_correct( 01617 png_ptr->background.green, g); 01618 back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, 01619 g); 01620 } 01621 01622 else 01623 { 01624 back_1.red = (png_byte)png_ptr->background.red; 01625 back_1.green = (png_byte)png_ptr->background.green; 01626 back_1.blue = (png_byte)png_ptr->background.blue; 01627 } 01628 } 01629 01630 for (i = 0; i < num_palette; i++) 01631 { 01632 if (i < (int)png_ptr->num_trans && 01633 png_ptr->trans_alpha[i] != 0xff) 01634 { 01635 if (png_ptr->trans_alpha[i] == 0) 01636 { 01637 palette[i] = back; 01638 } 01639 else /* if (png_ptr->trans_alpha[i] != 0xff) */ 01640 { 01641 png_byte v, w; 01642 01643 v = png_ptr->gamma_to_1[palette[i].red]; 01644 png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); 01645 palette[i].red = png_ptr->gamma_from_1[w]; 01646 01647 v = png_ptr->gamma_to_1[palette[i].green]; 01648 png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); 01649 palette[i].green = png_ptr->gamma_from_1[w]; 01650 01651 v = png_ptr->gamma_to_1[palette[i].blue]; 01652 png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); 01653 palette[i].blue = png_ptr->gamma_from_1[w]; 01654 } 01655 } 01656 else 01657 { 01658 palette[i].red = png_ptr->gamma_table[palette[i].red]; 01659 palette[i].green = png_ptr->gamma_table[palette[i].green]; 01660 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 01661 } 01662 } 01663 01664 /* Prevent the transformations being done again. 01665 * 01666 * NOTE: this is highly dubious; it removes the transformations in 01667 * place. This seems inconsistent with the general treatment of the 01668 * transformations elsewhere. 01669 */ 01670 png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); 01671 } /* color_type == PNG_COLOR_TYPE_PALETTE */ 01672 01673 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 01674 else /* color_type != PNG_COLOR_TYPE_PALETTE */ 01675 { 01676 int gs_sig, g_sig; 01677 png_fixed_point g = PNG_FP_1; /* Correction to linear */ 01678 png_fixed_point gs = PNG_FP_1; /* Correction to screen */ 01679 01680 switch (png_ptr->background_gamma_type) 01681 { 01682 case PNG_BACKGROUND_GAMMA_SCREEN: 01683 g = png_ptr->screen_gamma; 01684 /* gs = PNG_FP_1; */ 01685 break; 01686 01687 case PNG_BACKGROUND_GAMMA_FILE: 01688 g = png_reciprocal(png_ptr->gamma); 01689 gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); 01690 break; 01691 01692 case PNG_BACKGROUND_GAMMA_UNIQUE: 01693 g = png_reciprocal(png_ptr->background_gamma); 01694 gs = png_reciprocal2(png_ptr->background_gamma, 01695 png_ptr->screen_gamma); 01696 break; 01697 01698 default: 01699 png_error(png_ptr, "invalid background gamma type"); 01700 } 01701 01702 g_sig = png_gamma_significant(g); 01703 gs_sig = png_gamma_significant(gs); 01704 01705 if (g_sig) 01706 png_ptr->background_1.gray = png_gamma_correct(png_ptr, 01707 png_ptr->background.gray, g); 01708 01709 if (gs_sig) 01710 png_ptr->background.gray = png_gamma_correct(png_ptr, 01711 png_ptr->background.gray, gs); 01712 01713 if ((png_ptr->background.red != png_ptr->background.green) || 01714 (png_ptr->background.red != png_ptr->background.blue) || 01715 (png_ptr->background.red != png_ptr->background.gray)) 01716 { 01717 /* RGB or RGBA with color background */ 01718 if (g_sig) 01719 { 01720 png_ptr->background_1.red = png_gamma_correct(png_ptr, 01721 png_ptr->background.red, g); 01722 01723 png_ptr->background_1.green = png_gamma_correct(png_ptr, 01724 png_ptr->background.green, g); 01725 01726 png_ptr->background_1.blue = png_gamma_correct(png_ptr, 01727 png_ptr->background.blue, g); 01728 } 01729 01730 if (gs_sig) 01731 { 01732 png_ptr->background.red = png_gamma_correct(png_ptr, 01733 png_ptr->background.red, gs); 01734 01735 png_ptr->background.green = png_gamma_correct(png_ptr, 01736 png_ptr->background.green, gs); 01737 01738 png_ptr->background.blue = png_gamma_correct(png_ptr, 01739 png_ptr->background.blue, gs); 01740 } 01741 } 01742 01743 else 01744 { 01745 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 01746 png_ptr->background_1.red = png_ptr->background_1.green 01747 = png_ptr->background_1.blue = png_ptr->background_1.gray; 01748 01749 png_ptr->background.red = png_ptr->background.green 01750 = png_ptr->background.blue = png_ptr->background.gray; 01751 } 01752 01753 /* The background is now in screen gamma: */ 01754 png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; 01755 } /* color_type != PNG_COLOR_TYPE_PALETTE */ 01756 }/* png_ptr->transformations & PNG_BACKGROUND */ 01757 01758 else 01759 /* Transformation does not include PNG_BACKGROUND */ 01760 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 01761 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE 01762 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 01763 /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ 01764 && ((png_ptr->transformations & PNG_EXPAND) == 0 || 01765 (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) 01766 #endif 01767 ) 01768 { 01769 png_colorp palette = png_ptr->palette; 01770 int num_palette = png_ptr->num_palette; 01771 int i; 01772 01773 /*NOTE: there are other transformations that should probably be in here 01774 * too. 01775 */ 01776 for (i = 0; i < num_palette; i++) 01777 { 01778 palette[i].red = png_ptr->gamma_table[palette[i].red]; 01779 palette[i].green = png_ptr->gamma_table[palette[i].green]; 01780 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 01781 } 01782 01783 /* Done the gamma correction. */ 01784 png_ptr->transformations &= ~PNG_GAMMA; 01785 } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ 01786 } 01787 #ifdef PNG_READ_BACKGROUND_SUPPORTED 01788 else 01789 #endif 01790 #endif /* PNG_READ_GAMMA_SUPPORTED */ 01791 01792 #ifdef PNG_READ_BACKGROUND_SUPPORTED 01793 /* No GAMMA transformation (see the hanging else 4 lines above) */ 01794 if ((png_ptr->transformations & PNG_COMPOSE) && 01795 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 01796 { 01797 int i; 01798 int istop = (int)png_ptr->num_trans; 01799 png_color back; 01800 png_colorp palette = png_ptr->palette; 01801 01802 back.red = (png_byte)png_ptr->background.red; 01803 back.green = (png_byte)png_ptr->background.green; 01804 back.blue = (png_byte)png_ptr->background.blue; 01805 01806 for (i = 0; i < istop; i++) 01807 { 01808 if (png_ptr->trans_alpha[i] == 0) 01809 { 01810 palette[i] = back; 01811 } 01812 01813 else if (png_ptr->trans_alpha[i] != 0xff) 01814 { 01815 /* The png_composite() macro is defined in png.h */ 01816 png_composite(palette[i].red, palette[i].red, 01817 png_ptr->trans_alpha[i], back.red); 01818 01819 png_composite(palette[i].green, palette[i].green, 01820 png_ptr->trans_alpha[i], back.green); 01821 01822 png_composite(palette[i].blue, palette[i].blue, 01823 png_ptr->trans_alpha[i], back.blue); 01824 } 01825 } 01826 01827 png_ptr->transformations &= ~PNG_COMPOSE; 01828 } 01829 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 01830 01831 #ifdef PNG_READ_SHIFT_SUPPORTED 01832 if ((png_ptr->transformations & PNG_SHIFT) && 01833 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 01834 { 01835 int i; 01836 int istop = png_ptr->num_palette; 01837 int shift = 8 - png_ptr->sig_bit.red; 01838 01839 /* significant bits can be in the range 1 to 7 for a meaninful result, if 01840 * the number of significant bits is 0 then no shift is done (this is an 01841 * error condition which is silently ignored.) 01842 */ 01843 if (shift > 0 && shift < 8) for (i=0; i<istop; ++i) 01844 { 01845 int component = png_ptr->palette[i].red; 01846 01847 component >>= shift; 01848 png_ptr->palette[i].red = (png_byte)component; 01849 } 01850 01851 shift = 8 - png_ptr->sig_bit.green; 01852 if (shift > 0 && shift < 8) for (i=0; i<istop; ++i) 01853 { 01854 int component = png_ptr->palette[i].green; 01855 01856 component >>= shift; 01857 png_ptr->palette[i].green = (png_byte)component; 01858 } 01859 01860 shift = 8 - png_ptr->sig_bit.blue; 01861 if (shift > 0 && shift < 8) for (i=0; i<istop; ++i) 01862 { 01863 int component = png_ptr->palette[i].blue; 01864 01865 component >>= shift; 01866 png_ptr->palette[i].blue = (png_byte)component; 01867 } 01868 } 01869 #endif /* PNG_READ_SHIFT_SUPPORTED */ 01870 } 01871 01872 /* Modify the info structure to reflect the transformations. The 01873 * info should be updated so a PNG file could be written with it, 01874 * assuming the transformations result in valid PNG data. 01875 */ 01876 void /* PRIVATE */ 01877 png_read_transform_info(png_structp png_ptr, png_infop info_ptr) 01878 { 01879 png_debug(1, "in png_read_transform_info"); 01880 01881 #ifdef PNG_READ_EXPAND_SUPPORTED 01882 if (png_ptr->transformations & PNG_EXPAND) 01883 { 01884 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01885 { 01886 /* This check must match what actually happens in 01887 * png_do_expand_palette; if it ever checks the tRNS chunk to see if 01888 * it is all opaque we must do the same (at present it does not.) 01889 */ 01890 if (png_ptr->num_trans > 0) 01891 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 01892 01893 else 01894 info_ptr->color_type = PNG_COLOR_TYPE_RGB; 01895 01896 info_ptr->bit_depth = 8; 01897 info_ptr->num_trans = 0; 01898 } 01899 else 01900 { 01901 if (png_ptr->num_trans) 01902 { 01903 if (png_ptr->transformations & PNG_EXPAND_tRNS) 01904 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 01905 } 01906 if (info_ptr->bit_depth < 8) 01907 info_ptr->bit_depth = 8; 01908 01909 info_ptr->num_trans = 0; 01910 } 01911 } 01912 #endif 01913 01914 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 01915 defined(PNG_READ_ALPHA_MODE_SUPPORTED) 01916 /* The following is almost certainly wrong unless the background value is in 01917 * the screen space! 01918 */ 01919 if (png_ptr->transformations & PNG_COMPOSE) 01920 info_ptr->background = png_ptr->background; 01921 #endif 01922 01923 #ifdef PNG_READ_GAMMA_SUPPORTED 01924 /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), 01925 * however it seems that the code in png_init_read_transformations, which has 01926 * been called before this from png_read_update_info->png_read_start_row 01927 * sometimes does the gamma transform and cancels the flag. 01928 */ 01929 info_ptr->gamma = png_ptr->gamma; 01930 #endif 01931 01932 if (info_ptr->bit_depth == 16) 01933 { 01934 # ifdef PNG_READ_16BIT_SUPPORTED 01935 # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 01936 if (png_ptr->transformations & PNG_SCALE_16_TO_8) 01937 info_ptr->bit_depth = 8; 01938 # endif 01939 01940 # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 01941 if (png_ptr->transformations & PNG_16_TO_8) 01942 info_ptr->bit_depth = 8; 01943 # endif 01944 01945 # else 01946 /* No 16 bit support: force chopping 16-bit input down to 8, in this case 01947 * the app program can chose if both APIs are available by setting the 01948 * correct scaling to use. 01949 */ 01950 # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 01951 /* For compatibility with previous versions use the strip method by 01952 * default. This code works because if PNG_SCALE_16_TO_8 is already 01953 * set the code below will do that in preference to the chop. 01954 */ 01955 png_ptr->transformations |= PNG_16_TO_8; 01956 info_ptr->bit_depth = 8; 01957 # else 01958 01959 # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 01960 png_ptr->transformations |= PNG_SCALE_16_TO_8; 01961 info_ptr->bit_depth = 8; 01962 # else 01963 01964 CONFIGURATION ERROR: you must enable at least one 16 to 8 method 01965 # endif 01966 # endif 01967 #endif /* !READ_16BIT_SUPPORTED */ 01968 } 01969 01970 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 01971 if (png_ptr->transformations & PNG_GRAY_TO_RGB) 01972 info_ptr->color_type = (png_byte)(info_ptr->color_type | 01973 PNG_COLOR_MASK_COLOR); 01974 #endif 01975 01976 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 01977 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 01978 info_ptr->color_type = (png_byte)(info_ptr->color_type & 01979 ~PNG_COLOR_MASK_COLOR); 01980 #endif 01981 01982 #ifdef PNG_READ_QUANTIZE_SUPPORTED 01983 if (png_ptr->transformations & PNG_QUANTIZE) 01984 { 01985 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 01986 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 01987 png_ptr->palette_lookup && info_ptr->bit_depth == 8) 01988 { 01989 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 01990 } 01991 } 01992 #endif 01993 01994 #ifdef PNG_READ_EXPAND_16_SUPPORTED 01995 if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && 01996 info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) 01997 { 01998 info_ptr->bit_depth = 16; 01999 } 02000 #endif 02001 02002 #ifdef PNG_READ_PACK_SUPPORTED 02003 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) 02004 info_ptr->bit_depth = 8; 02005 #endif 02006 02007 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 02008 info_ptr->channels = 1; 02009 02010 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 02011 info_ptr->channels = 3; 02012 02013 else 02014 info_ptr->channels = 1; 02015 02016 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 02017 if (png_ptr->transformations & PNG_STRIP_ALPHA) 02018 { 02019 info_ptr->color_type = (png_byte)(info_ptr->color_type & 02020 ~PNG_COLOR_MASK_ALPHA); 02021 info_ptr->num_trans = 0; 02022 } 02023 #endif 02024 02025 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 02026 info_ptr->channels++; 02027 02028 #ifdef PNG_READ_FILLER_SUPPORTED 02029 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 02030 if ((png_ptr->transformations & PNG_FILLER) && 02031 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 02032 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) 02033 { 02034 info_ptr->channels++; 02035 /* If adding a true alpha channel not just filler */ 02036 if (png_ptr->transformations & PNG_ADD_ALPHA) 02037 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 02038 } 02039 #endif 02040 02041 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 02042 defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 02043 if (png_ptr->transformations & PNG_USER_TRANSFORM) 02044 { 02045 if (info_ptr->bit_depth < png_ptr->user_transform_depth) 02046 info_ptr->bit_depth = png_ptr->user_transform_depth; 02047 02048 if (info_ptr->channels < png_ptr->user_transform_channels) 02049 info_ptr->channels = png_ptr->user_transform_channels; 02050 } 02051 #endif 02052 02053 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 02054 info_ptr->bit_depth); 02055 02056 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 02057 02058 /* Adding in 1.5.4: cache the above value in png_struct so that we can later 02059 * check in png_rowbytes that the user buffer won't get overwritten. Note 02060 * that the field is not always set - if png_read_update_info isn't called 02061 * the application has to either not do any transforms or get the calculation 02062 * right itself. 02063 */ 02064 png_ptr->info_rowbytes = info_ptr->rowbytes; 02065 02066 #ifndef PNG_READ_EXPAND_SUPPORTED 02067 if (png_ptr) 02068 return; 02069 #endif 02070 } 02071 02072 /* Transform the row. The order of transformations is significant, 02073 * and is very touchy. If you add a transformation, take care to 02074 * decide how it fits in with the other transformations here. 02075 */ 02076 void /* PRIVATE */ 02077 png_do_read_transformations(png_structp png_ptr, png_row_infop row_info) 02078 { 02079 png_debug(1, "in png_do_read_transformations"); 02080 02081 if (png_ptr->row_buf == NULL) 02082 { 02083 /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this 02084 * error is incredibly rare and incredibly easy to debug without this 02085 * information. 02086 */ 02087 png_error(png_ptr, "NULL row buffer"); 02088 } 02089 02090 /* The following is debugging; prior to 1.5.4 the code was never compiled in; 02091 * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro 02092 * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for 02093 * selected new APIs to ensure that there is no API change. 02094 */ 02095 if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && 02096 !(png_ptr->flags & PNG_FLAG_ROW_INIT)) 02097 { 02098 /* Application has failed to call either png_read_start_image() or 02099 * png_read_update_info() after setting transforms that expand pixels. 02100 * This check added to libpng-1.2.19 (but not enabled until 1.5.4). 02101 */ 02102 png_error(png_ptr, "Uninitialized row"); 02103 } 02104 02105 #ifdef PNG_READ_EXPAND_SUPPORTED 02106 if (png_ptr->transformations & PNG_EXPAND) 02107 { 02108 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 02109 { 02110 png_do_expand_palette(row_info, png_ptr->row_buf + 1, 02111 png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); 02112 } 02113 02114 else 02115 { 02116 if (png_ptr->num_trans && 02117 (png_ptr->transformations & PNG_EXPAND_tRNS)) 02118 png_do_expand(row_info, png_ptr->row_buf + 1, 02119 &(png_ptr->trans_color)); 02120 02121 else 02122 png_do_expand(row_info, png_ptr->row_buf + 1, 02123 NULL); 02124 } 02125 } 02126 #endif 02127 02128 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 02129 if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 02130 !(png_ptr->transformations & PNG_COMPOSE) && 02131 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 02132 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 02133 png_do_strip_channel(row_info, png_ptr->row_buf + 1, 02134 0 /* at_start == false, because SWAP_ALPHA happens later */); 02135 #endif 02136 02137 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 02138 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 02139 { 02140 int rgb_error = 02141 png_do_rgb_to_gray(png_ptr, row_info, 02142 png_ptr->row_buf + 1); 02143 02144 if (rgb_error) 02145 { 02146 png_ptr->rgb_to_gray_status=1; 02147 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 02148 PNG_RGB_TO_GRAY_WARN) 02149 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 02150 02151 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 02152 PNG_RGB_TO_GRAY_ERR) 02153 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 02154 } 02155 } 02156 #endif 02157 02158 /* From Andreas Dilger e-mail to png-implement, 26 March 1998: 02159 * 02160 * In most cases, the "simple transparency" should be done prior to doing 02161 * gray-to-RGB, or you will have to test 3x as many bytes to check if a 02162 * pixel is transparent. You would also need to make sure that the 02163 * transparency information is upgraded to RGB. 02164 * 02165 * To summarize, the current flow is: 02166 * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 02167 * with background "in place" if transparent, 02168 * convert to RGB if necessary 02169 * - Gray + alpha -> composite with gray background and remove alpha bytes, 02170 * convert to RGB if necessary 02171 * 02172 * To support RGB backgrounds for gray images we need: 02173 * - Gray + simple transparency -> convert to RGB + simple transparency, 02174 * compare 3 or 6 bytes and composite with 02175 * background "in place" if transparent 02176 * (3x compare/pixel compared to doing 02177 * composite with gray bkgrnd) 02178 * - Gray + alpha -> convert to RGB + alpha, composite with background and 02179 * remove alpha bytes (3x float 02180 * operations/pixel compared with composite 02181 * on gray background) 02182 * 02183 * Greg's change will do this. The reason it wasn't done before is for 02184 * performance, as this increases the per-pixel operations. If we would check 02185 * in advance if the background was gray or RGB, and position the gray-to-RGB 02186 * transform appropriately, then it would save a lot of work/time. 02187 */ 02188 02189 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 02190 /* If gray -> RGB, do so now only if background is non-gray; else do later 02191 * for performance reasons 02192 */ 02193 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 02194 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 02195 png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 02196 #endif 02197 02198 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ 02199 (defined PNG_READ_ALPHA_MODE_SUPPORTED) 02200 if (png_ptr->transformations & PNG_COMPOSE) 02201 png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); 02202 #endif 02203 02204 #ifdef PNG_READ_GAMMA_SUPPORTED 02205 if ((png_ptr->transformations & PNG_GAMMA) && 02206 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 02207 /* Because RGB_TO_GRAY does the gamma transform. */ 02208 !(png_ptr->transformations & PNG_RGB_TO_GRAY) && 02209 #endif 02210 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ 02211 (defined PNG_READ_ALPHA_MODE_SUPPORTED) 02212 /* Because PNG_COMPOSE does the gamma transform if there is something to 02213 * do (if there is an alpha channel or transparency.) 02214 */ 02215 !((png_ptr->transformations & PNG_COMPOSE) && 02216 ((png_ptr->num_trans != 0) || 02217 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && 02218 #endif 02219 /* Because png_init_read_transformations transforms the palette, unless 02220 * RGB_TO_GRAY will do the transform. 02221 */ 02222 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 02223 png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); 02224 #endif 02225 02226 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 02227 if ((png_ptr->transformations & PNG_STRIP_ALPHA) && 02228 (png_ptr->transformations & PNG_COMPOSE) && 02229 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 02230 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 02231 png_do_strip_channel(row_info, png_ptr->row_buf + 1, 02232 0 /* at_start == false, because SWAP_ALPHA happens later */); 02233 #endif 02234 02235 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 02236 if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && 02237 (row_info->color_type & PNG_COLOR_MASK_ALPHA)) 02238 png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); 02239 #endif 02240 02241 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 02242 if (png_ptr->transformations & PNG_SCALE_16_TO_8) 02243 png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); 02244 #endif 02245 02246 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 02247 /* There is no harm in doing both of these because only one has any effect, 02248 * by putting the 'scale' option first if the app asks for scale (either by 02249 * calling the API or in a TRANSFORM flag) this is what happens. 02250 */ 02251 if (png_ptr->transformations & PNG_16_TO_8) 02252 png_do_chop(row_info, png_ptr->row_buf + 1); 02253 #endif 02254 02255 #ifdef PNG_READ_QUANTIZE_SUPPORTED 02256 if (png_ptr->transformations & PNG_QUANTIZE) 02257 { 02258 png_do_quantize(row_info, png_ptr->row_buf + 1, 02259 png_ptr->palette_lookup, png_ptr->quantize_index); 02260 02261 if (row_info->rowbytes == 0) 02262 png_error(png_ptr, "png_do_quantize returned rowbytes=0"); 02263 } 02264 #endif /* PNG_READ_QUANTIZE_SUPPORTED */ 02265 02266 #ifdef PNG_READ_EXPAND_16_SUPPORTED 02267 /* Do the expansion now, after all the arithmetic has been done. Notice 02268 * that previous transformations can handle the PNG_EXPAND_16 flag if this 02269 * is efficient (particularly true in the case of gamma correction, where 02270 * better accuracy results faster!) 02271 */ 02272 if (png_ptr->transformations & PNG_EXPAND_16) 02273 png_do_expand_16(row_info, png_ptr->row_buf + 1); 02274 #endif 02275 02276 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 02277 /*NOTE: moved here in 1.5.4 (from much later in this list.) */ 02278 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 02279 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 02280 png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); 02281 #endif 02282 02283 #ifdef PNG_READ_INVERT_SUPPORTED 02284 if (png_ptr->transformations & PNG_INVERT_MONO) 02285 png_do_invert(row_info, png_ptr->row_buf + 1); 02286 #endif 02287 02288 #ifdef PNG_READ_SHIFT_SUPPORTED 02289 if (png_ptr->transformations & PNG_SHIFT) 02290 png_do_unshift(row_info, png_ptr->row_buf + 1, 02291 &(png_ptr->shift)); 02292 #endif 02293 02294 #ifdef PNG_READ_PACK_SUPPORTED 02295 if (png_ptr->transformations & PNG_PACK) 02296 png_do_unpack(row_info, png_ptr->row_buf + 1); 02297 #endif 02298 02299 #ifdef PNG_READ_BGR_SUPPORTED 02300 if (png_ptr->transformations & PNG_BGR) 02301 png_do_bgr(row_info, png_ptr->row_buf + 1); 02302 #endif 02303 02304 #ifdef PNG_READ_PACKSWAP_SUPPORTED 02305 if (png_ptr->transformations & PNG_PACKSWAP) 02306 png_do_packswap(row_info, png_ptr->row_buf + 1); 02307 #endif 02308 02309 #ifdef PNG_READ_FILLER_SUPPORTED 02310 if (png_ptr->transformations & PNG_FILLER) 02311 png_do_read_filler(row_info, png_ptr->row_buf + 1, 02312 (png_uint_32)png_ptr->filler, png_ptr->flags); 02313 #endif 02314 02315 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 02316 if (png_ptr->transformations & PNG_INVERT_ALPHA) 02317 png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); 02318 #endif 02319 02320 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 02321 if (png_ptr->transformations & PNG_SWAP_ALPHA) 02322 png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); 02323 #endif 02324 02325 #ifdef PNG_READ_16BIT_SUPPORTED 02326 #ifdef PNG_READ_SWAP_SUPPORTED 02327 if (png_ptr->transformations & PNG_SWAP_BYTES) 02328 png_do_swap(row_info, png_ptr->row_buf + 1); 02329 #endif 02330 #endif 02331 02332 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 02333 if (png_ptr->transformations & PNG_USER_TRANSFORM) 02334 { 02335 if (png_ptr->read_user_transform_fn != NULL) 02336 (*(png_ptr->read_user_transform_fn)) /* User read transform function */ 02337 (png_ptr, /* png_ptr */ 02338 row_info, /* row_info: */ 02339 /* png_uint_32 width; width of row */ 02340 /* png_size_t rowbytes; number of bytes in row */ 02341 /* png_byte color_type; color type of pixels */ 02342 /* png_byte bit_depth; bit depth of samples */ 02343 /* png_byte channels; number of channels (1-4) */ 02344 /* png_byte pixel_depth; bits per pixel (depth*channels) */ 02345 png_ptr->row_buf + 1); /* start of pixel data for row */ 02346 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED 02347 if (png_ptr->user_transform_depth) 02348 row_info->bit_depth = png_ptr->user_transform_depth; 02349 02350 if (png_ptr->user_transform_channels) 02351 row_info->channels = png_ptr->user_transform_channels; 02352 #endif 02353 row_info->pixel_depth = (png_byte)(row_info->bit_depth * 02354 row_info->channels); 02355 02356 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); 02357 } 02358 #endif 02359 } 02360 02361 #ifdef PNG_READ_PACK_SUPPORTED 02362 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 02363 * without changing the actual values. Thus, if you had a row with 02364 * a bit depth of 1, you would end up with bytes that only contained 02365 * the numbers 0 or 1. If you would rather they contain 0 and 255, use 02366 * png_do_shift() after this. 02367 */ 02368 void /* PRIVATE */ 02369 png_do_unpack(png_row_infop row_info, png_bytep row) 02370 { 02371 png_debug(1, "in png_do_unpack"); 02372 02373 if (row_info->bit_depth < 8) 02374 { 02375 png_uint_32 i; 02376 png_uint_32 row_width=row_info->width; 02377 02378 switch (row_info->bit_depth) 02379 { 02380 case 1: 02381 { 02382 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 02383 png_bytep dp = row + (png_size_t)row_width - 1; 02384 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); 02385 for (i = 0; i < row_width; i++) 02386 { 02387 *dp = (png_byte)((*sp >> shift) & 0x01); 02388 02389 if (shift == 7) 02390 { 02391 shift = 0; 02392 sp--; 02393 } 02394 02395 else 02396 shift++; 02397 02398 dp--; 02399 } 02400 break; 02401 } 02402 02403 case 2: 02404 { 02405 02406 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 02407 png_bytep dp = row + (png_size_t)row_width - 1; 02408 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 02409 for (i = 0; i < row_width; i++) 02410 { 02411 *dp = (png_byte)((*sp >> shift) & 0x03); 02412 02413 if (shift == 6) 02414 { 02415 shift = 0; 02416 sp--; 02417 } 02418 02419 else 02420 shift += 2; 02421 02422 dp--; 02423 } 02424 break; 02425 } 02426 02427 case 4: 02428 { 02429 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 02430 png_bytep dp = row + (png_size_t)row_width - 1; 02431 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 02432 for (i = 0; i < row_width; i++) 02433 { 02434 *dp = (png_byte)((*sp >> shift) & 0x0f); 02435 02436 if (shift == 4) 02437 { 02438 shift = 0; 02439 sp--; 02440 } 02441 02442 else 02443 shift = 4; 02444 02445 dp--; 02446 } 02447 break; 02448 } 02449 02450 default: 02451 break; 02452 } 02453 row_info->bit_depth = 8; 02454 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 02455 row_info->rowbytes = row_width * row_info->channels; 02456 } 02457 } 02458 #endif 02459 02460 #ifdef PNG_READ_SHIFT_SUPPORTED 02461 /* Reverse the effects of png_do_shift. This routine merely shifts the 02462 * pixels back to their significant bits values. Thus, if you have 02463 * a row of bit depth 8, but only 5 are significant, this will shift 02464 * the values back to 0 through 31. 02465 */ 02466 void /* PRIVATE */ 02467 png_do_unshift(png_row_infop row_info, png_bytep row, 02468 png_const_color_8p sig_bits) 02469 { 02470 int color_type; 02471 02472 png_debug(1, "in png_do_unshift"); 02473 02474 /* The palette case has already been handled in the _init routine. */ 02475 color_type = row_info->color_type; 02476 02477 if (color_type != PNG_COLOR_TYPE_PALETTE) 02478 { 02479 int shift[4]; 02480 int channels = 0; 02481 int bit_depth = row_info->bit_depth; 02482 02483 if (color_type & PNG_COLOR_MASK_COLOR) 02484 { 02485 shift[channels++] = bit_depth - sig_bits->red; 02486 shift[channels++] = bit_depth - sig_bits->green; 02487 shift[channels++] = bit_depth - sig_bits->blue; 02488 } 02489 02490 else 02491 { 02492 shift[channels++] = bit_depth - sig_bits->gray; 02493 } 02494 02495 if (color_type & PNG_COLOR_MASK_ALPHA) 02496 { 02497 shift[channels++] = bit_depth - sig_bits->alpha; 02498 } 02499 02500 { 02501 int c, have_shift; 02502 02503 for (c = have_shift = 0; c < channels; ++c) 02504 { 02505 /* A shift of more than the bit depth is an error condition but it 02506 * gets ignored here. 02507 */ 02508 if (shift[c] <= 0 || shift[c] >= bit_depth) 02509 shift[c] = 0; 02510 02511 else 02512 have_shift = 1; 02513 } 02514 02515 if (!have_shift) 02516 return; 02517 } 02518 02519 switch (bit_depth) 02520 { 02521 default: 02522 /* Must be 1bpp gray: should not be here! */ 02523 /* NOTREACHED */ 02524 break; 02525 02526 case 2: 02527 /* Must be 2bpp gray */ 02528 /* assert(channels == 1 && shift[0] == 1) */ 02529 { 02530 png_bytep bp = row; 02531 png_bytep bp_end = bp + row_info->rowbytes; 02532 02533 while (bp < bp_end) 02534 { 02535 int b = (*bp >> 1) & 0x55; 02536 *bp++ = (png_byte)b; 02537 } 02538 break; 02539 } 02540 02541 case 4: 02542 /* Must be 4bpp gray */ 02543 /* assert(channels == 1) */ 02544 { 02545 png_bytep bp = row; 02546 png_bytep bp_end = bp + row_info->rowbytes; 02547 int gray_shift = shift[0]; 02548 int mask = 0xf >> gray_shift; 02549 02550 mask |= mask << 4; 02551 02552 while (bp < bp_end) 02553 { 02554 int b = (*bp >> gray_shift) & mask; 02555 *bp++ = (png_byte)b; 02556 } 02557 break; 02558 } 02559 02560 case 8: 02561 /* Single byte components, G, GA, RGB, RGBA */ 02562 { 02563 png_bytep bp = row; 02564 png_bytep bp_end = bp + row_info->rowbytes; 02565 int channel = 0; 02566 02567 while (bp < bp_end) 02568 { 02569 int b = *bp >> shift[channel]; 02570 if (++channel >= channels) 02571 channel = 0; 02572 *bp++ = (png_byte)b; 02573 } 02574 break; 02575 } 02576 02577 #ifdef PNG_READ_16BIT_SUPPORTED 02578 case 16: 02579 /* Double byte components, G, GA, RGB, RGBA */ 02580 { 02581 png_bytep bp = row; 02582 png_bytep bp_end = bp + row_info->rowbytes; 02583 int channel = 0; 02584 02585 while (bp < bp_end) 02586 { 02587 int value = (bp[0] << 8) + bp[1]; 02588 02589 value >>= shift[channel]; 02590 if (++channel >= channels) 02591 channel = 0; 02592 *bp++ = (png_byte)(value >> 8); 02593 *bp++ = (png_byte)(value & 0xff); 02594 } 02595 break; 02596 } 02597 #endif 02598 } 02599 } 02600 } 02601 #endif 02602 02603 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 02604 /* Scale rows of bit depth 16 down to 8 accurately */ 02605 void /* PRIVATE */ 02606 png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) 02607 { 02608 png_debug(1, "in png_do_scale_16_to_8"); 02609 02610 if (row_info->bit_depth == 16) 02611 { 02612 png_bytep sp = row; /* source */ 02613 png_bytep dp = row; /* destination */ 02614 png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 02615 02616 while (sp < ep) 02617 { 02618 /* The input is an array of 16 bit components, these must be scaled to 02619 * 8 bits each. For a 16 bit value V the required value (from the PNG 02620 * specification) is: 02621 * 02622 * (V * 255) / 65535 02623 * 02624 * This reduces to round(V / 257), or floor((V + 128.5)/257) 02625 * 02626 * Represent V as the two byte value vhi.vlo. Make a guess that the 02627 * result is the top byte of V, vhi, then the correction to this value 02628 * is: 02629 * 02630 * error = floor(((V-vhi.vhi) + 128.5) / 257) 02631 * = floor(((vlo-vhi) + 128.5) / 257) 02632 * 02633 * This can be approximated using integer arithmetic (and a signed 02634 * shift): 02635 * 02636 * error = (vlo-vhi+128) >> 8; 02637 * 02638 * The approximate differs from the exact answer only when (vlo-vhi) is 02639 * 128; it then gives a correction of +1 when the exact correction is 02640 * 0. This gives 128 errors. The exact answer (correct for all 16 bit 02641 * input values) is: 02642 * 02643 * error = (vlo-vhi+128)*65535 >> 24; 02644 * 02645 * An alternative arithmetic calculation which also gives no errors is: 02646 * 02647 * (V * 255 + 32895) >> 16 02648 */ 02649 02650 png_int_32 tmp = *sp++; /* must be signed! */ 02651 tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; 02652 *dp++ = (png_byte)tmp; 02653 } 02654 02655 row_info->bit_depth = 8; 02656 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 02657 row_info->rowbytes = row_info->width * row_info->channels; 02658 } 02659 } 02660 #endif 02661 02662 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 02663 void /* PRIVATE */ 02664 /* Simply discard the low byte. This was the default behavior prior 02665 * to libpng-1.5.4. 02666 */ 02667 png_do_chop(png_row_infop row_info, png_bytep row) 02668 { 02669 png_debug(1, "in png_do_chop"); 02670 02671 if (row_info->bit_depth == 16) 02672 { 02673 png_bytep sp = row; /* source */ 02674 png_bytep dp = row; /* destination */ 02675 png_bytep ep = sp + row_info->rowbytes; /* end+1 */ 02676 02677 while (sp < ep) 02678 { 02679 *dp++ = *sp; 02680 sp += 2; /* skip low byte */ 02681 } 02682 02683 row_info->bit_depth = 8; 02684 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 02685 row_info->rowbytes = row_info->width * row_info->channels; 02686 } 02687 } 02688 #endif 02689 02690 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 02691 void /* PRIVATE */ 02692 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 02693 { 02694 png_debug(1, "in png_do_read_swap_alpha"); 02695 02696 { 02697 png_uint_32 row_width = row_info->width; 02698 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 02699 { 02700 /* This converts from RGBA to ARGB */ 02701 if (row_info->bit_depth == 8) 02702 { 02703 png_bytep sp = row + row_info->rowbytes; 02704 png_bytep dp = sp; 02705 png_byte save; 02706 png_uint_32 i; 02707 02708 for (i = 0; i < row_width; i++) 02709 { 02710 save = *(--sp); 02711 *(--dp) = *(--sp); 02712 *(--dp) = *(--sp); 02713 *(--dp) = *(--sp); 02714 *(--dp) = save; 02715 } 02716 } 02717 02718 #ifdef PNG_READ_16BIT_SUPPORTED 02719 /* This converts from RRGGBBAA to AARRGGBB */ 02720 else 02721 { 02722 png_bytep sp = row + row_info->rowbytes; 02723 png_bytep dp = sp; 02724 png_byte save[2]; 02725 png_uint_32 i; 02726 02727 for (i = 0; i < row_width; i++) 02728 { 02729 save[0] = *(--sp); 02730 save[1] = *(--sp); 02731 *(--dp) = *(--sp); 02732 *(--dp) = *(--sp); 02733 *(--dp) = *(--sp); 02734 *(--dp) = *(--sp); 02735 *(--dp) = *(--sp); 02736 *(--dp) = *(--sp); 02737 *(--dp) = save[0]; 02738 *(--dp) = save[1]; 02739 } 02740 } 02741 #endif 02742 } 02743 02744 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 02745 { 02746 /* This converts from GA to AG */ 02747 if (row_info->bit_depth == 8) 02748 { 02749 png_bytep sp = row + row_info->rowbytes; 02750 png_bytep dp = sp; 02751 png_byte save; 02752 png_uint_32 i; 02753 02754 for (i = 0; i < row_width; i++) 02755 { 02756 save = *(--sp); 02757 *(--dp) = *(--sp); 02758 *(--dp) = save; 02759 } 02760 } 02761 02762 #ifdef PNG_READ_16BIT_SUPPORTED 02763 /* This converts from GGAA to AAGG */ 02764 else 02765 { 02766 png_bytep sp = row + row_info->rowbytes; 02767 png_bytep dp = sp; 02768 png_byte save[2]; 02769 png_uint_32 i; 02770 02771 for (i = 0; i < row_width; i++) 02772 { 02773 save[0] = *(--sp); 02774 save[1] = *(--sp); 02775 *(--dp) = *(--sp); 02776 *(--dp) = *(--sp); 02777 *(--dp) = save[0]; 02778 *(--dp) = save[1]; 02779 } 02780 } 02781 #endif 02782 } 02783 } 02784 } 02785 #endif 02786 02787 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 02788 void /* PRIVATE */ 02789 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 02790 { 02791 png_uint_32 row_width; 02792 png_debug(1, "in png_do_read_invert_alpha"); 02793 02794 row_width = row_info->width; 02795 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 02796 { 02797 if (row_info->bit_depth == 8) 02798 { 02799 /* This inverts the alpha channel in RGBA */ 02800 png_bytep sp = row + row_info->rowbytes; 02801 png_bytep dp = sp; 02802 png_uint_32 i; 02803 02804 for (i = 0; i < row_width; i++) 02805 { 02806 *(--dp) = (png_byte)(255 - *(--sp)); 02807 02808 /* This does nothing: 02809 *(--dp) = *(--sp); 02810 *(--dp) = *(--sp); 02811 *(--dp) = *(--sp); 02812 We can replace it with: 02813 */ 02814 sp-=3; 02815 dp=sp; 02816 } 02817 } 02818 02819 #ifdef PNG_READ_16BIT_SUPPORTED 02820 /* This inverts the alpha channel in RRGGBBAA */ 02821 else 02822 { 02823 png_bytep sp = row + row_info->rowbytes; 02824 png_bytep dp = sp; 02825 png_uint_32 i; 02826 02827 for (i = 0; i < row_width; i++) 02828 { 02829 *(--dp) = (png_byte)(255 - *(--sp)); 02830 *(--dp) = (png_byte)(255 - *(--sp)); 02831 02832 /* This does nothing: 02833 *(--dp) = *(--sp); 02834 *(--dp) = *(--sp); 02835 *(--dp) = *(--sp); 02836 *(--dp) = *(--sp); 02837 *(--dp) = *(--sp); 02838 *(--dp) = *(--sp); 02839 We can replace it with: 02840 */ 02841 sp-=6; 02842 dp=sp; 02843 } 02844 } 02845 #endif 02846 } 02847 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 02848 { 02849 if (row_info->bit_depth == 8) 02850 { 02851 /* This inverts the alpha channel in GA */ 02852 png_bytep sp = row + row_info->rowbytes; 02853 png_bytep dp = sp; 02854 png_uint_32 i; 02855 02856 for (i = 0; i < row_width; i++) 02857 { 02858 *(--dp) = (png_byte)(255 - *(--sp)); 02859 *(--dp) = *(--sp); 02860 } 02861 } 02862 02863 #ifdef PNG_READ_16BIT_SUPPORTED 02864 else 02865 { 02866 /* This inverts the alpha channel in GGAA */ 02867 png_bytep sp = row + row_info->rowbytes; 02868 png_bytep dp = sp; 02869 png_uint_32 i; 02870 02871 for (i = 0; i < row_width; i++) 02872 { 02873 *(--dp) = (png_byte)(255 - *(--sp)); 02874 *(--dp) = (png_byte)(255 - *(--sp)); 02875 /* 02876 *(--dp) = *(--sp); 02877 *(--dp) = *(--sp); 02878 */ 02879 sp-=2; 02880 dp=sp; 02881 } 02882 } 02883 #endif 02884 } 02885 } 02886 #endif 02887 02888 #ifdef PNG_READ_FILLER_SUPPORTED 02889 /* Add filler channel if we have RGB color */ 02890 void /* PRIVATE */ 02891 png_do_read_filler(png_row_infop row_info, png_bytep row, 02892 png_uint_32 filler, png_uint_32 flags) 02893 { 02894 png_uint_32 i; 02895 png_uint_32 row_width = row_info->width; 02896 02897 #ifdef PNG_READ_16BIT_SUPPORTED 02898 png_byte hi_filler = (png_byte)((filler>>8) & 0xff); 02899 #endif 02900 png_byte lo_filler = (png_byte)(filler & 0xff); 02901 02902 png_debug(1, "in png_do_read_filler"); 02903 02904 if ( 02905 row_info->color_type == PNG_COLOR_TYPE_GRAY) 02906 { 02907 if (row_info->bit_depth == 8) 02908 { 02909 if (flags & PNG_FLAG_FILLER_AFTER) 02910 { 02911 /* This changes the data from G to GX */ 02912 png_bytep sp = row + (png_size_t)row_width; 02913 png_bytep dp = sp + (png_size_t)row_width; 02914 for (i = 1; i < row_width; i++) 02915 { 02916 *(--dp) = lo_filler; 02917 *(--dp) = *(--sp); 02918 } 02919 *(--dp) = lo_filler; 02920 row_info->channels = 2; 02921 row_info->pixel_depth = 16; 02922 row_info->rowbytes = row_width * 2; 02923 } 02924 02925 else 02926 { 02927 /* This changes the data from G to XG */ 02928 png_bytep sp = row + (png_size_t)row_width; 02929 png_bytep dp = sp + (png_size_t)row_width; 02930 for (i = 0; i < row_width; i++) 02931 { 02932 *(--dp) = *(--sp); 02933 *(--dp) = lo_filler; 02934 } 02935 row_info->channels = 2; 02936 row_info->pixel_depth = 16; 02937 row_info->rowbytes = row_width * 2; 02938 } 02939 } 02940 02941 #ifdef PNG_READ_16BIT_SUPPORTED 02942 else if (row_info->bit_depth == 16) 02943 { 02944 if (flags & PNG_FLAG_FILLER_AFTER) 02945 { 02946 /* This changes the data from GG to GGXX */ 02947 png_bytep sp = row + (png_size_t)row_width * 2; 02948 png_bytep dp = sp + (png_size_t)row_width * 2; 02949 for (i = 1; i < row_width; i++) 02950 { 02951 *(--dp) = hi_filler; 02952 *(--dp) = lo_filler; 02953 *(--dp) = *(--sp); 02954 *(--dp) = *(--sp); 02955 } 02956 *(--dp) = hi_filler; 02957 *(--dp) = lo_filler; 02958 row_info->channels = 2; 02959 row_info->pixel_depth = 32; 02960 row_info->rowbytes = row_width * 4; 02961 } 02962 02963 else 02964 { 02965 /* This changes the data from GG to XXGG */ 02966 png_bytep sp = row + (png_size_t)row_width * 2; 02967 png_bytep dp = sp + (png_size_t)row_width * 2; 02968 for (i = 0; i < row_width; i++) 02969 { 02970 *(--dp) = *(--sp); 02971 *(--dp) = *(--sp); 02972 *(--dp) = hi_filler; 02973 *(--dp) = lo_filler; 02974 } 02975 row_info->channels = 2; 02976 row_info->pixel_depth = 32; 02977 row_info->rowbytes = row_width * 4; 02978 } 02979 } 02980 #endif 02981 } /* COLOR_TYPE == GRAY */ 02982 else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 02983 { 02984 if (row_info->bit_depth == 8) 02985 { 02986 if (flags & PNG_FLAG_FILLER_AFTER) 02987 { 02988 /* This changes the data from RGB to RGBX */ 02989 png_bytep sp = row + (png_size_t)row_width * 3; 02990 png_bytep dp = sp + (png_size_t)row_width; 02991 for (i = 1; i < row_width; i++) 02992 { 02993 *(--dp) = lo_filler; 02994 *(--dp) = *(--sp); 02995 *(--dp) = *(--sp); 02996 *(--dp) = *(--sp); 02997 } 02998 *(--dp) = lo_filler; 02999 row_info->channels = 4; 03000 row_info->pixel_depth = 32; 03001 row_info->rowbytes = row_width * 4; 03002 } 03003 03004 else 03005 { 03006 /* This changes the data from RGB to XRGB */ 03007 png_bytep sp = row + (png_size_t)row_width * 3; 03008 png_bytep dp = sp + (png_size_t)row_width; 03009 for (i = 0; i < row_width; i++) 03010 { 03011 *(--dp) = *(--sp); 03012 *(--dp) = *(--sp); 03013 *(--dp) = *(--sp); 03014 *(--dp) = lo_filler; 03015 } 03016 row_info->channels = 4; 03017 row_info->pixel_depth = 32; 03018 row_info->rowbytes = row_width * 4; 03019 } 03020 } 03021 03022 #ifdef PNG_READ_16BIT_SUPPORTED 03023 else if (row_info->bit_depth == 16) 03024 { 03025 if (flags & PNG_FLAG_FILLER_AFTER) 03026 { 03027 /* This changes the data from RRGGBB to RRGGBBXX */ 03028 png_bytep sp = row + (png_size_t)row_width * 6; 03029 png_bytep dp = sp + (png_size_t)row_width * 2; 03030 for (i = 1; i < row_width; i++) 03031 { 03032 *(--dp) = hi_filler; 03033 *(--dp) = lo_filler; 03034 *(--dp) = *(--sp); 03035 *(--dp) = *(--sp); 03036 *(--dp) = *(--sp); 03037 *(--dp) = *(--sp); 03038 *(--dp) = *(--sp); 03039 *(--dp) = *(--sp); 03040 } 03041 *(--dp) = hi_filler; 03042 *(--dp) = lo_filler; 03043 row_info->channels = 4; 03044 row_info->pixel_depth = 64; 03045 row_info->rowbytes = row_width * 8; 03046 } 03047 03048 else 03049 { 03050 /* This changes the data from RRGGBB to XXRRGGBB */ 03051 png_bytep sp = row + (png_size_t)row_width * 6; 03052 png_bytep dp = sp + (png_size_t)row_width * 2; 03053 for (i = 0; i < row_width; i++) 03054 { 03055 *(--dp) = *(--sp); 03056 *(--dp) = *(--sp); 03057 *(--dp) = *(--sp); 03058 *(--dp) = *(--sp); 03059 *(--dp) = *(--sp); 03060 *(--dp) = *(--sp); 03061 *(--dp) = hi_filler; 03062 *(--dp) = lo_filler; 03063 } 03064 03065 row_info->channels = 4; 03066 row_info->pixel_depth = 64; 03067 row_info->rowbytes = row_width * 8; 03068 } 03069 } 03070 #endif 03071 } /* COLOR_TYPE == RGB */ 03072 } 03073 #endif 03074 03075 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 03076 /* Expand grayscale files to RGB, with or without alpha */ 03077 void /* PRIVATE */ 03078 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 03079 { 03080 png_uint_32 i; 03081 png_uint_32 row_width = row_info->width; 03082 03083 png_debug(1, "in png_do_gray_to_rgb"); 03084 03085 if (row_info->bit_depth >= 8 && 03086 !(row_info->color_type & PNG_COLOR_MASK_COLOR)) 03087 { 03088 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 03089 { 03090 if (row_info->bit_depth == 8) 03091 { 03092 /* This changes G to RGB */ 03093 png_bytep sp = row + (png_size_t)row_width - 1; 03094 png_bytep dp = sp + (png_size_t)row_width * 2; 03095 for (i = 0; i < row_width; i++) 03096 { 03097 *(dp--) = *sp; 03098 *(dp--) = *sp; 03099 *(dp--) = *(sp--); 03100 } 03101 } 03102 03103 else 03104 { 03105 /* This changes GG to RRGGBB */ 03106 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 03107 png_bytep dp = sp + (png_size_t)row_width * 4; 03108 for (i = 0; i < row_width; i++) 03109 { 03110 *(dp--) = *sp; 03111 *(dp--) = *(sp - 1); 03112 *(dp--) = *sp; 03113 *(dp--) = *(sp - 1); 03114 *(dp--) = *(sp--); 03115 *(dp--) = *(sp--); 03116 } 03117 } 03118 } 03119 03120 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 03121 { 03122 if (row_info->bit_depth == 8) 03123 { 03124 /* This changes GA to RGBA */ 03125 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 03126 png_bytep dp = sp + (png_size_t)row_width * 2; 03127 for (i = 0; i < row_width; i++) 03128 { 03129 *(dp--) = *(sp--); 03130 *(dp--) = *sp; 03131 *(dp--) = *sp; 03132 *(dp--) = *(sp--); 03133 } 03134 } 03135 03136 else 03137 { 03138 /* This changes GGAA to RRGGBBAA */ 03139 png_bytep sp = row + (png_size_t)row_width * 4 - 1; 03140 png_bytep dp = sp + (png_size_t)row_width * 4; 03141 for (i = 0; i < row_width; i++) 03142 { 03143 *(dp--) = *(sp--); 03144 *(dp--) = *(sp--); 03145 *(dp--) = *sp; 03146 *(dp--) = *(sp - 1); 03147 *(dp--) = *sp; 03148 *(dp--) = *(sp - 1); 03149 *(dp--) = *(sp--); 03150 *(dp--) = *(sp--); 03151 } 03152 } 03153 } 03154 row_info->channels = (png_byte)(row_info->channels + 2); 03155 row_info->color_type |= PNG_COLOR_MASK_COLOR; 03156 row_info->pixel_depth = (png_byte)(row_info->channels * 03157 row_info->bit_depth); 03158 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 03159 } 03160 } 03161 #endif 03162 03163 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 03164 /* Reduce RGB files to grayscale, with or without alpha 03165 * using the equation given in Poynton's ColorFAQ of 1998-01-04 at 03166 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but 03167 * versions dated 1998 through November 2002 have been archived at 03168 * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ 03169 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) 03170 * Charles Poynton poynton at poynton.com 03171 * 03172 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 03173 * 03174 * which can be expressed with integers as 03175 * 03176 * Y = (6969 * R + 23434 * G + 2365 * B)/32768 03177 * 03178 * Poynton's current link (as of January 2003 through July 2011): 03179 * <http://www.poynton.com/notes/colour_and_gamma/> 03180 * has changed the numbers slightly: 03181 * 03182 * Y = 0.2126*R + 0.7152*G + 0.0722*B 03183 * 03184 * which can be expressed with integers as 03185 * 03186 * Y = (6966 * R + 23436 * G + 2366 * B)/32768 03187 * 03188 * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 03189 * end point chromaticities and the D65 white point. Depending on the 03190 * precision used for the D65 white point this produces a variety of different 03191 * numbers, however if the four decimal place value used in ITU-R Rec 709 is 03192 * used (0.3127,0.3290) the Y calculation would be: 03193 * 03194 * Y = (6968 * R + 23435 * G + 2366 * B)/32768 03195 * 03196 * While this is correct the rounding results in an overflow for white, because 03197 * the sum of the rounded coefficients is 32769, not 32768. Consequently 03198 * libpng uses, instead, the closest non-overflowing approximation: 03199 * 03200 * Y = (6968 * R + 23434 * G + 2366 * B)/32768 03201 * 03202 * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk 03203 * (including an sRGB chunk) then the chromaticities are used to calculate the 03204 * coefficients. See the chunk handling in pngrutil.c for more information. 03205 * 03206 * In all cases the calculation is to be done in a linear colorspace. If no 03207 * gamma information is available to correct the encoding of the original RGB 03208 * values this results in an implicit assumption that the original PNG RGB 03209 * values were linear. 03210 * 03211 * Other integer coefficents can be used via png_set_rgb_to_gray(). Because 03212 * the API takes just red and green coefficients the blue coefficient is 03213 * calculated to make the sum 32768. This will result in different rounding 03214 * to that used above. 03215 */ 03216 int /* PRIVATE */ 03217 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) 03218 03219 { 03220 int rgb_error = 0; 03221 03222 png_debug(1, "in png_do_rgb_to_gray"); 03223 03224 if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && 03225 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 03226 { 03227 PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 03228 PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 03229 PNG_CONST png_uint_32 bc = 32768 - rc - gc; 03230 PNG_CONST png_uint_32 row_width = row_info->width; 03231 PNG_CONST int have_alpha = 03232 (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; 03233 03234 if (row_info->bit_depth == 8) 03235 { 03236 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 03237 /* Notice that gamma to/from 1 are not necessarily inverses (if 03238 * there is an overall gamma correction). Prior to 1.5.5 this code 03239 * checked the linearized values for equality; this doesn't match 03240 * the documentation, the original values must be checked. 03241 */ 03242 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 03243 { 03244 png_bytep sp = row; 03245 png_bytep dp = row; 03246 png_uint_32 i; 03247 03248 for (i = 0; i < row_width; i++) 03249 { 03250 png_byte red = *(sp++); 03251 png_byte green = *(sp++); 03252 png_byte blue = *(sp++); 03253 03254 if (red != green || red != blue) 03255 { 03256 red = png_ptr->gamma_to_1[red]; 03257 green = png_ptr->gamma_to_1[green]; 03258 blue = png_ptr->gamma_to_1[blue]; 03259 03260 rgb_error |= 1; 03261 *(dp++) = png_ptr->gamma_from_1[ 03262 (rc*red + gc*green + bc*blue + 16384)>>15]; 03263 } 03264 03265 else 03266 { 03267 /* If there is no overall correction the table will not be 03268 * set. 03269 */ 03270 if (png_ptr->gamma_table != NULL) 03271 red = png_ptr->gamma_table[red]; 03272 03273 *(dp++) = red; 03274 } 03275 03276 if (have_alpha) 03277 *(dp++) = *(sp++); 03278 } 03279 } 03280 else 03281 #endif 03282 { 03283 png_bytep sp = row; 03284 png_bytep dp = row; 03285 png_uint_32 i; 03286 03287 for (i = 0; i < row_width; i++) 03288 { 03289 png_byte red = *(sp++); 03290 png_byte green = *(sp++); 03291 png_byte blue = *(sp++); 03292 03293 if (red != green || red != blue) 03294 { 03295 rgb_error |= 1; 03296 /*NOTE: this is the historical approach which simply 03297 * truncates the results. 03298 */ 03299 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 03300 } 03301 03302 else 03303 *(dp++) = red; 03304 03305 if (have_alpha) 03306 *(dp++) = *(sp++); 03307 } 03308 } 03309 } 03310 03311 else /* RGB bit_depth == 16 */ 03312 { 03313 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 03314 if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) 03315 { 03316 png_bytep sp = row; 03317 png_bytep dp = row; 03318 png_uint_32 i; 03319 03320 for (i = 0; i < row_width; i++) 03321 { 03322 png_uint_16 red, green, blue, w; 03323 03324 red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03325 green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03326 blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03327 03328 if (red == green && red == blue) 03329 { 03330 if (png_ptr->gamma_16_table != NULL) 03331 w = png_ptr->gamma_16_table[(red&0xff) 03332 >> png_ptr->gamma_shift][red>>8]; 03333 03334 else 03335 w = red; 03336 } 03337 03338 else 03339 { 03340 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) 03341 >> png_ptr->gamma_shift][red>>8]; 03342 png_uint_16 green_1 = 03343 png_ptr->gamma_16_to_1[(green&0xff) >> 03344 png_ptr->gamma_shift][green>>8]; 03345 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) 03346 >> png_ptr->gamma_shift][blue>>8]; 03347 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 03348 + bc*blue_1 + 16384)>>15); 03349 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 03350 png_ptr->gamma_shift][gray16 >> 8]; 03351 rgb_error |= 1; 03352 } 03353 03354 *(dp++) = (png_byte)((w>>8) & 0xff); 03355 *(dp++) = (png_byte)(w & 0xff); 03356 03357 if (have_alpha) 03358 { 03359 *(dp++) = *(sp++); 03360 *(dp++) = *(sp++); 03361 } 03362 } 03363 } 03364 else 03365 #endif 03366 { 03367 png_bytep sp = row; 03368 png_bytep dp = row; 03369 png_uint_32 i; 03370 03371 for (i = 0; i < row_width; i++) 03372 { 03373 png_uint_16 red, green, blue, gray16; 03374 03375 red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03376 green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03377 blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; 03378 03379 if (red != green || red != blue) 03380 rgb_error |= 1; 03381 03382 /* From 1.5.5 in the 16 bit case do the accurate conversion even 03383 * in the 'fast' case - this is because this is where the code 03384 * ends up when handling linear 16 bit data. 03385 */ 03386 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> 03387 15); 03388 *(dp++) = (png_byte)((gray16>>8) & 0xff); 03389 *(dp++) = (png_byte)(gray16 & 0xff); 03390 03391 if (have_alpha) 03392 { 03393 *(dp++) = *(sp++); 03394 *(dp++) = *(sp++); 03395 } 03396 } 03397 } 03398 } 03399 03400 row_info->channels = (png_byte)(row_info->channels - 2); 03401 row_info->color_type = (png_byte)(row_info->color_type & 03402 ~PNG_COLOR_MASK_COLOR); 03403 row_info->pixel_depth = (png_byte)(row_info->channels * 03404 row_info->bit_depth); 03405 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 03406 } 03407 return rgb_error; 03408 } 03409 #endif 03410 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 03411 03412 #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED 03413 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth 03414 * large of png_color. This lets grayscale images be treated as 03415 * paletted. Most useful for gamma correction and simplification 03416 * of code. This API is not used internally. 03417 */ 03418 void PNGAPI 03419 png_build_grayscale_palette(int bit_depth, png_colorp palette) 03420 { 03421 int num_palette; 03422 int color_inc; 03423 int i; 03424 int v; 03425 03426 png_debug(1, "in png_do_build_grayscale_palette"); 03427 03428 if (palette == NULL) 03429 return; 03430 03431 switch (bit_depth) 03432 { 03433 case 1: 03434 num_palette = 2; 03435 color_inc = 0xff; 03436 break; 03437 03438 case 2: 03439 num_palette = 4; 03440 color_inc = 0x55; 03441 break; 03442 03443 case 4: 03444 num_palette = 16; 03445 color_inc = 0x11; 03446 break; 03447 03448 case 8: 03449 num_palette = 256; 03450 color_inc = 1; 03451 break; 03452 03453 default: 03454 num_palette = 0; 03455 color_inc = 0; 03456 break; 03457 } 03458 03459 for (i = 0, v = 0; i < num_palette; i++, v += color_inc) 03460 { 03461 palette[i].red = (png_byte)v; 03462 palette[i].green = (png_byte)v; 03463 palette[i].blue = (png_byte)v; 03464 } 03465 } 03466 #endif 03467 03468 03469 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 03470 #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ 03471 (defined PNG_READ_ALPHA_MODE_SUPPORTED) 03472 /* Replace any alpha or transparency with the supplied background color. 03473 * "background" is already in the screen gamma, while "background_1" is 03474 * at a gamma of 1.0. Paletted files have already been taken care of. 03475 */ 03476 void /* PRIVATE */ 03477 png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr) 03478 { 03479 #ifdef PNG_READ_GAMMA_SUPPORTED 03480 png_const_bytep gamma_table = png_ptr->gamma_table; 03481 png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; 03482 png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; 03483 png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; 03484 png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; 03485 png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; 03486 int gamma_shift = png_ptr->gamma_shift; 03487 #endif 03488 03489 png_bytep sp; 03490 png_uint_32 i; 03491 png_uint_32 row_width = row_info->width; 03492 int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; 03493 int shift; 03494 03495 png_debug(1, "in png_do_compose"); 03496 03497 { 03498 switch (row_info->color_type) 03499 { 03500 case PNG_COLOR_TYPE_GRAY: 03501 { 03502 switch (row_info->bit_depth) 03503 { 03504 case 1: 03505 { 03506 sp = row; 03507 shift = 7; 03508 for (i = 0; i < row_width; i++) 03509 { 03510 if ((png_uint_16)((*sp >> shift) & 0x01) 03511 == png_ptr->trans_color.gray) 03512 { 03513 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); 03514 *sp |= (png_byte)(png_ptr->background.gray << shift); 03515 } 03516 03517 if (!shift) 03518 { 03519 shift = 7; 03520 sp++; 03521 } 03522 03523 else 03524 shift--; 03525 } 03526 break; 03527 } 03528 03529 case 2: 03530 { 03531 #ifdef PNG_READ_GAMMA_SUPPORTED 03532 if (gamma_table != NULL) 03533 { 03534 sp = row; 03535 shift = 6; 03536 for (i = 0; i < row_width; i++) 03537 { 03538 if ((png_uint_16)((*sp >> shift) & 0x03) 03539 == png_ptr->trans_color.gray) 03540 { 03541 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 03542 *sp |= (png_byte)(png_ptr->background.gray << shift); 03543 } 03544 03545 else 03546 { 03547 png_byte p = (png_byte)((*sp >> shift) & 0x03); 03548 png_byte g = (png_byte)((gamma_table [p | (p << 2) | 03549 (p << 4) | (p << 6)] >> 6) & 0x03); 03550 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 03551 *sp |= (png_byte)(g << shift); 03552 } 03553 03554 if (!shift) 03555 { 03556 shift = 6; 03557 sp++; 03558 } 03559 03560 else 03561 shift -= 2; 03562 } 03563 } 03564 03565 else 03566 #endif 03567 { 03568 sp = row; 03569 shift = 6; 03570 for (i = 0; i < row_width; i++) 03571 { 03572 if ((png_uint_16)((*sp >> shift) & 0x03) 03573 == png_ptr->trans_color.gray) 03574 { 03575 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 03576 *sp |= (png_byte)(png_ptr->background.gray << shift); 03577 } 03578 03579 if (!shift) 03580 { 03581 shift = 6; 03582 sp++; 03583 } 03584 03585 else 03586 shift -= 2; 03587 } 03588 } 03589 break; 03590 } 03591 03592 case 4: 03593 { 03594 #ifdef PNG_READ_GAMMA_SUPPORTED 03595 if (gamma_table != NULL) 03596 { 03597 sp = row; 03598 shift = 4; 03599 for (i = 0; i < row_width; i++) 03600 { 03601 if ((png_uint_16)((*sp >> shift) & 0x0f) 03602 == png_ptr->trans_color.gray) 03603 { 03604 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 03605 *sp |= (png_byte)(png_ptr->background.gray << shift); 03606 } 03607 03608 else 03609 { 03610 png_byte p = (png_byte)((*sp >> shift) & 0x0f); 03611 png_byte g = (png_byte)((gamma_table[p | 03612 (p << 4)] >> 4) & 0x0f); 03613 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 03614 *sp |= (png_byte)(g << shift); 03615 } 03616 03617 if (!shift) 03618 { 03619 shift = 4; 03620 sp++; 03621 } 03622 03623 else 03624 shift -= 4; 03625 } 03626 } 03627 03628 else 03629 #endif 03630 { 03631 sp = row; 03632 shift = 4; 03633 for (i = 0; i < row_width; i++) 03634 { 03635 if ((png_uint_16)((*sp >> shift) & 0x0f) 03636 == png_ptr->trans_color.gray) 03637 { 03638 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 03639 *sp |= (png_byte)(png_ptr->background.gray << shift); 03640 } 03641 03642 if (!shift) 03643 { 03644 shift = 4; 03645 sp++; 03646 } 03647 03648 else 03649 shift -= 4; 03650 } 03651 } 03652 break; 03653 } 03654 03655 case 8: 03656 { 03657 #ifdef PNG_READ_GAMMA_SUPPORTED 03658 if (gamma_table != NULL) 03659 { 03660 sp = row; 03661 for (i = 0; i < row_width; i++, sp++) 03662 { 03663 if (*sp == png_ptr->trans_color.gray) 03664 *sp = (png_byte)png_ptr->background.gray; 03665 03666 else 03667 *sp = gamma_table[*sp]; 03668 } 03669 } 03670 else 03671 #endif 03672 { 03673 sp = row; 03674 for (i = 0; i < row_width; i++, sp++) 03675 { 03676 if (*sp == png_ptr->trans_color.gray) 03677 *sp = (png_byte)png_ptr->background.gray; 03678 } 03679 } 03680 break; 03681 } 03682 03683 case 16: 03684 { 03685 #ifdef PNG_READ_GAMMA_SUPPORTED 03686 if (gamma_16 != NULL) 03687 { 03688 sp = row; 03689 for (i = 0; i < row_width; i++, sp += 2) 03690 { 03691 png_uint_16 v; 03692 03693 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03694 03695 if (v == png_ptr->trans_color.gray) 03696 { 03697 /* Background is already in screen gamma */ 03698 *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); 03699 *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 03700 } 03701 03702 else 03703 { 03704 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03705 *sp = (png_byte)((v >> 8) & 0xff); 03706 *(sp + 1) = (png_byte)(v & 0xff); 03707 } 03708 } 03709 } 03710 else 03711 #endif 03712 { 03713 sp = row; 03714 for (i = 0; i < row_width; i++, sp += 2) 03715 { 03716 png_uint_16 v; 03717 03718 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03719 03720 if (v == png_ptr->trans_color.gray) 03721 { 03722 *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); 03723 *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 03724 } 03725 } 03726 } 03727 break; 03728 } 03729 03730 default: 03731 break; 03732 } 03733 break; 03734 } 03735 03736 case PNG_COLOR_TYPE_RGB: 03737 { 03738 if (row_info->bit_depth == 8) 03739 { 03740 #ifdef PNG_READ_GAMMA_SUPPORTED 03741 if (gamma_table != NULL) 03742 { 03743 sp = row; 03744 for (i = 0; i < row_width; i++, sp += 3) 03745 { 03746 if (*sp == png_ptr->trans_color.red && 03747 *(sp + 1) == png_ptr->trans_color.green && 03748 *(sp + 2) == png_ptr->trans_color.blue) 03749 { 03750 *sp = (png_byte)png_ptr->background.red; 03751 *(sp + 1) = (png_byte)png_ptr->background.green; 03752 *(sp + 2) = (png_byte)png_ptr->background.blue; 03753 } 03754 03755 else 03756 { 03757 *sp = gamma_table[*sp]; 03758 *(sp + 1) = gamma_table[*(sp + 1)]; 03759 *(sp + 2) = gamma_table[*(sp + 2)]; 03760 } 03761 } 03762 } 03763 else 03764 #endif 03765 { 03766 sp = row; 03767 for (i = 0; i < row_width; i++, sp += 3) 03768 { 03769 if (*sp == png_ptr->trans_color.red && 03770 *(sp + 1) == png_ptr->trans_color.green && 03771 *(sp + 2) == png_ptr->trans_color.blue) 03772 { 03773 *sp = (png_byte)png_ptr->background.red; 03774 *(sp + 1) = (png_byte)png_ptr->background.green; 03775 *(sp + 2) = (png_byte)png_ptr->background.blue; 03776 } 03777 } 03778 } 03779 } 03780 else /* if (row_info->bit_depth == 16) */ 03781 { 03782 #ifdef PNG_READ_GAMMA_SUPPORTED 03783 if (gamma_16 != NULL) 03784 { 03785 sp = row; 03786 for (i = 0; i < row_width; i++, sp += 6) 03787 { 03788 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03789 03790 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 03791 + *(sp + 3)); 03792 03793 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 03794 + *(sp + 5)); 03795 03796 if (r == png_ptr->trans_color.red && 03797 g == png_ptr->trans_color.green && 03798 b == png_ptr->trans_color.blue) 03799 { 03800 /* Background is already in screen gamma */ 03801 *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 03802 *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 03803 *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); 03804 *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); 03805 *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); 03806 *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 03807 } 03808 03809 else 03810 { 03811 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03812 *sp = (png_byte)((v >> 8) & 0xff); 03813 *(sp + 1) = (png_byte)(v & 0xff); 03814 03815 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 03816 *(sp + 2) = (png_byte)((v >> 8) & 0xff); 03817 *(sp + 3) = (png_byte)(v & 0xff); 03818 03819 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 03820 *(sp + 4) = (png_byte)((v >> 8) & 0xff); 03821 *(sp + 5) = (png_byte)(v & 0xff); 03822 } 03823 } 03824 } 03825 03826 else 03827 #endif 03828 { 03829 sp = row; 03830 for (i = 0; i < row_width; i++, sp += 6) 03831 { 03832 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03833 03834 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 03835 + *(sp + 3)); 03836 03837 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 03838 + *(sp + 5)); 03839 03840 if (r == png_ptr->trans_color.red && 03841 g == png_ptr->trans_color.green && 03842 b == png_ptr->trans_color.blue) 03843 { 03844 *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 03845 *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 03846 *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); 03847 *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); 03848 *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); 03849 *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 03850 } 03851 } 03852 } 03853 } 03854 break; 03855 } 03856 03857 case PNG_COLOR_TYPE_GRAY_ALPHA: 03858 { 03859 if (row_info->bit_depth == 8) 03860 { 03861 #ifdef PNG_READ_GAMMA_SUPPORTED 03862 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 03863 gamma_table != NULL) 03864 { 03865 sp = row; 03866 for (i = 0; i < row_width; i++, sp += 2) 03867 { 03868 png_uint_16 a = *(sp + 1); 03869 03870 if (a == 0xff) 03871 *sp = gamma_table[*sp]; 03872 03873 else if (a == 0) 03874 { 03875 /* Background is already in screen gamma */ 03876 *sp = (png_byte)png_ptr->background.gray; 03877 } 03878 03879 else 03880 { 03881 png_byte v, w; 03882 03883 v = gamma_to_1[*sp]; 03884 png_composite(w, v, a, png_ptr->background_1.gray); 03885 if (!optimize) 03886 w = gamma_from_1[w]; 03887 *sp = w; 03888 } 03889 } 03890 } 03891 else 03892 #endif 03893 { 03894 sp = row; 03895 for (i = 0; i < row_width; i++, sp += 2) 03896 { 03897 png_byte a = *(sp + 1); 03898 03899 if (a == 0) 03900 *sp = (png_byte)png_ptr->background.gray; 03901 03902 else if (a < 0xff) 03903 png_composite(*sp, *sp, a, png_ptr->background_1.gray); 03904 } 03905 } 03906 } 03907 else /* if (png_ptr->bit_depth == 16) */ 03908 { 03909 #ifdef PNG_READ_GAMMA_SUPPORTED 03910 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 03911 gamma_16_to_1 != NULL) 03912 { 03913 sp = row; 03914 for (i = 0; i < row_width; i++, sp += 4) 03915 { 03916 png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 03917 + *(sp + 3)); 03918 03919 if (a == (png_uint_16)0xffff) 03920 { 03921 png_uint_16 v; 03922 03923 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03924 *sp = (png_byte)((v >> 8) & 0xff); 03925 *(sp + 1) = (png_byte)(v & 0xff); 03926 } 03927 03928 else if (a == 0) 03929 { 03930 /* Background is already in screen gamma */ 03931 *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); 03932 *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 03933 } 03934 03935 else 03936 { 03937 png_uint_16 g, v, w; 03938 03939 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 03940 png_composite_16(v, g, a, png_ptr->background_1.gray); 03941 if (optimize) 03942 w = v; 03943 else 03944 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; 03945 *sp = (png_byte)((w >> 8) & 0xff); 03946 *(sp + 1) = (png_byte)(w & 0xff); 03947 } 03948 } 03949 } 03950 else 03951 #endif 03952 { 03953 sp = row; 03954 for (i = 0; i < row_width; i++, sp += 4) 03955 { 03956 png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) 03957 + *(sp + 3)); 03958 03959 if (a == 0) 03960 { 03961 *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); 03962 *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); 03963 } 03964 03965 else if (a < 0xffff) 03966 { 03967 png_uint_16 g, v; 03968 03969 g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03970 png_composite_16(v, g, a, png_ptr->background_1.gray); 03971 *sp = (png_byte)((v >> 8) & 0xff); 03972 *(sp + 1) = (png_byte)(v & 0xff); 03973 } 03974 } 03975 } 03976 } 03977 break; 03978 } 03979 03980 case PNG_COLOR_TYPE_RGB_ALPHA: 03981 { 03982 if (row_info->bit_depth == 8) 03983 { 03984 #ifdef PNG_READ_GAMMA_SUPPORTED 03985 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 03986 gamma_table != NULL) 03987 { 03988 sp = row; 03989 for (i = 0; i < row_width; i++, sp += 4) 03990 { 03991 png_byte a = *(sp + 3); 03992 03993 if (a == 0xff) 03994 { 03995 *sp = gamma_table[*sp]; 03996 *(sp + 1) = gamma_table[*(sp + 1)]; 03997 *(sp + 2) = gamma_table[*(sp + 2)]; 03998 } 03999 04000 else if (a == 0) 04001 { 04002 /* Background is already in screen gamma */ 04003 *sp = (png_byte)png_ptr->background.red; 04004 *(sp + 1) = (png_byte)png_ptr->background.green; 04005 *(sp + 2) = (png_byte)png_ptr->background.blue; 04006 } 04007 04008 else 04009 { 04010 png_byte v, w; 04011 04012 v = gamma_to_1[*sp]; 04013 png_composite(w, v, a, png_ptr->background_1.red); 04014 if (!optimize) w = gamma_from_1[w]; 04015 *sp = w; 04016 04017 v = gamma_to_1[*(sp + 1)]; 04018 png_composite(w, v, a, png_ptr->background_1.green); 04019 if (!optimize) w = gamma_from_1[w]; 04020 *(sp + 1) = w; 04021 04022 v = gamma_to_1[*(sp + 2)]; 04023 png_composite(w, v, a, png_ptr->background_1.blue); 04024 if (!optimize) w = gamma_from_1[w]; 04025 *(sp + 2) = w; 04026 } 04027 } 04028 } 04029 else 04030 #endif 04031 { 04032 sp = row; 04033 for (i = 0; i < row_width; i++, sp += 4) 04034 { 04035 png_byte a = *(sp + 3); 04036 04037 if (a == 0) 04038 { 04039 *sp = (png_byte)png_ptr->background.red; 04040 *(sp + 1) = (png_byte)png_ptr->background.green; 04041 *(sp + 2) = (png_byte)png_ptr->background.blue; 04042 } 04043 04044 else if (a < 0xff) 04045 { 04046 png_composite(*sp, *sp, a, png_ptr->background.red); 04047 04048 png_composite(*(sp + 1), *(sp + 1), a, 04049 png_ptr->background.green); 04050 04051 png_composite(*(sp + 2), *(sp + 2), a, 04052 png_ptr->background.blue); 04053 } 04054 } 04055 } 04056 } 04057 else /* if (row_info->bit_depth == 16) */ 04058 { 04059 #ifdef PNG_READ_GAMMA_SUPPORTED 04060 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 04061 gamma_16_to_1 != NULL) 04062 { 04063 sp = row; 04064 for (i = 0; i < row_width; i++, sp += 8) 04065 { 04066 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 04067 << 8) + (png_uint_16)(*(sp + 7))); 04068 04069 if (a == (png_uint_16)0xffff) 04070 { 04071 png_uint_16 v; 04072 04073 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 04074 *sp = (png_byte)((v >> 8) & 0xff); 04075 *(sp + 1) = (png_byte)(v & 0xff); 04076 04077 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 04078 *(sp + 2) = (png_byte)((v >> 8) & 0xff); 04079 *(sp + 3) = (png_byte)(v & 0xff); 04080 04081 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 04082 *(sp + 4) = (png_byte)((v >> 8) & 0xff); 04083 *(sp + 5) = (png_byte)(v & 0xff); 04084 } 04085 04086 else if (a == 0) 04087 { 04088 /* Background is already in screen gamma */ 04089 *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 04090 *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 04091 *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); 04092 *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); 04093 *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); 04094 *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 04095 } 04096 04097 else 04098 { 04099 png_uint_16 v, w; 04100 04101 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 04102 png_composite_16(w, v, a, png_ptr->background_1.red); 04103 if (!optimize) 04104 w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 04105 *sp = (png_byte)((w >> 8) & 0xff); 04106 *(sp + 1) = (png_byte)(w & 0xff); 04107 04108 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 04109 png_composite_16(w, v, a, png_ptr->background_1.green); 04110 if (!optimize) 04111 w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 04112 04113 *(sp + 2) = (png_byte)((w >> 8) & 0xff); 04114 *(sp + 3) = (png_byte)(w & 0xff); 04115 04116 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 04117 png_composite_16(w, v, a, png_ptr->background_1.blue); 04118 if (!optimize) 04119 w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 04120 04121 *(sp + 4) = (png_byte)((w >> 8) & 0xff); 04122 *(sp + 5) = (png_byte)(w & 0xff); 04123 } 04124 } 04125 } 04126 04127 else 04128 #endif 04129 { 04130 sp = row; 04131 for (i = 0; i < row_width; i++, sp += 8) 04132 { 04133 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 04134 << 8) + (png_uint_16)(*(sp + 7))); 04135 04136 if (a == 0) 04137 { 04138 *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); 04139 *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); 04140 *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); 04141 *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); 04142 *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); 04143 *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); 04144 } 04145 04146 else if (a < 0xffff) 04147 { 04148 png_uint_16 v; 04149 04150 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 04151 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 04152 + *(sp + 3)); 04153 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 04154 + *(sp + 5)); 04155 04156 png_composite_16(v, r, a, png_ptr->background.red); 04157 *sp = (png_byte)((v >> 8) & 0xff); 04158 *(sp + 1) = (png_byte)(v & 0xff); 04159 04160 png_composite_16(v, g, a, png_ptr->background.green); 04161 *(sp + 2) = (png_byte)((v >> 8) & 0xff); 04162 *(sp + 3) = (png_byte)(v & 0xff); 04163 04164 png_composite_16(v, b, a, png_ptr->background.blue); 04165 *(sp + 4) = (png_byte)((v >> 8) & 0xff); 04166 *(sp + 5) = (png_byte)(v & 0xff); 04167 } 04168 } 04169 } 04170 } 04171 break; 04172 } 04173 04174 default: 04175 break; 04176 } 04177 } 04178 } 04179 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ 04180 04181 #ifdef PNG_READ_GAMMA_SUPPORTED 04182 /* Gamma correct the image, avoiding the alpha channel. Make sure 04183 * you do this after you deal with the transparency issue on grayscale 04184 * or RGB images. If your bit depth is 8, use gamma_table, if it 04185 * is 16, use gamma_16_table and gamma_shift. Build these with 04186 * build_gamma_table(). 04187 */ 04188 void /* PRIVATE */ 04189 png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr) 04190 { 04191 png_const_bytep gamma_table = png_ptr->gamma_table; 04192 png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; 04193 int gamma_shift = png_ptr->gamma_shift; 04194 04195 png_bytep sp; 04196 png_uint_32 i; 04197 png_uint_32 row_width=row_info->width; 04198 04199 png_debug(1, "in png_do_gamma"); 04200 04201 if (((row_info->bit_depth <= 8 && gamma_table != NULL) || 04202 (row_info->bit_depth == 16 && gamma_16_table != NULL))) 04203 { 04204 switch (row_info->color_type) 04205 { 04206 case PNG_COLOR_TYPE_RGB: 04207 { 04208 if (row_info->bit_depth == 8) 04209 { 04210 sp = row; 04211 for (i = 0; i < row_width; i++) 04212 { 04213 *sp = gamma_table[*sp]; 04214 sp++; 04215 *sp = gamma_table[*sp]; 04216 sp++; 04217 *sp = gamma_table[*sp]; 04218 sp++; 04219 } 04220 } 04221 04222 else /* if (row_info->bit_depth == 16) */ 04223 { 04224 sp = row; 04225 for (i = 0; i < row_width; i++) 04226 { 04227 png_uint_16 v; 04228 04229 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04230 *sp = (png_byte)((v >> 8) & 0xff); 04231 *(sp + 1) = (png_byte)(v & 0xff); 04232 sp += 2; 04233 04234 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04235 *sp = (png_byte)((v >> 8) & 0xff); 04236 *(sp + 1) = (png_byte)(v & 0xff); 04237 sp += 2; 04238 04239 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04240 *sp = (png_byte)((v >> 8) & 0xff); 04241 *(sp + 1) = (png_byte)(v & 0xff); 04242 sp += 2; 04243 } 04244 } 04245 break; 04246 } 04247 04248 case PNG_COLOR_TYPE_RGB_ALPHA: 04249 { 04250 if (row_info->bit_depth == 8) 04251 { 04252 sp = row; 04253 for (i = 0; i < row_width; i++) 04254 { 04255 *sp = gamma_table[*sp]; 04256 sp++; 04257 04258 *sp = gamma_table[*sp]; 04259 sp++; 04260 04261 *sp = gamma_table[*sp]; 04262 sp++; 04263 04264 sp++; 04265 } 04266 } 04267 04268 else /* if (row_info->bit_depth == 16) */ 04269 { 04270 sp = row; 04271 for (i = 0; i < row_width; i++) 04272 { 04273 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04274 *sp = (png_byte)((v >> 8) & 0xff); 04275 *(sp + 1) = (png_byte)(v & 0xff); 04276 sp += 2; 04277 04278 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04279 *sp = (png_byte)((v >> 8) & 0xff); 04280 *(sp + 1) = (png_byte)(v & 0xff); 04281 sp += 2; 04282 04283 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04284 *sp = (png_byte)((v >> 8) & 0xff); 04285 *(sp + 1) = (png_byte)(v & 0xff); 04286 sp += 4; 04287 } 04288 } 04289 break; 04290 } 04291 04292 case PNG_COLOR_TYPE_GRAY_ALPHA: 04293 { 04294 if (row_info->bit_depth == 8) 04295 { 04296 sp = row; 04297 for (i = 0; i < row_width; i++) 04298 { 04299 *sp = gamma_table[*sp]; 04300 sp += 2; 04301 } 04302 } 04303 04304 else /* if (row_info->bit_depth == 16) */ 04305 { 04306 sp = row; 04307 for (i = 0; i < row_width; i++) 04308 { 04309 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04310 *sp = (png_byte)((v >> 8) & 0xff); 04311 *(sp + 1) = (png_byte)(v & 0xff); 04312 sp += 4; 04313 } 04314 } 04315 break; 04316 } 04317 04318 case PNG_COLOR_TYPE_GRAY: 04319 { 04320 if (row_info->bit_depth == 2) 04321 { 04322 sp = row; 04323 for (i = 0; i < row_width; i += 4) 04324 { 04325 int a = *sp & 0xc0; 04326 int b = *sp & 0x30; 04327 int c = *sp & 0x0c; 04328 int d = *sp & 0x03; 04329 04330 *sp = (png_byte)( 04331 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 04332 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 04333 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 04334 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 04335 sp++; 04336 } 04337 } 04338 04339 if (row_info->bit_depth == 4) 04340 { 04341 sp = row; 04342 for (i = 0; i < row_width; i += 2) 04343 { 04344 int msb = *sp & 0xf0; 04345 int lsb = *sp & 0x0f; 04346 04347 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 04348 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 04349 sp++; 04350 } 04351 } 04352 04353 else if (row_info->bit_depth == 8) 04354 { 04355 sp = row; 04356 for (i = 0; i < row_width; i++) 04357 { 04358 *sp = gamma_table[*sp]; 04359 sp++; 04360 } 04361 } 04362 04363 else if (row_info->bit_depth == 16) 04364 { 04365 sp = row; 04366 for (i = 0; i < row_width; i++) 04367 { 04368 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 04369 *sp = (png_byte)((v >> 8) & 0xff); 04370 *(sp + 1) = (png_byte)(v & 0xff); 04371 sp += 2; 04372 } 04373 } 04374 break; 04375 } 04376 04377 default: 04378 break; 04379 } 04380 } 04381 } 04382 #endif 04383 04384 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 04385 /* Encode the alpha channel to the output gamma (the input channel is always 04386 * linear.) Called only with color types that have an alpha channel. Needs the 04387 * from_1 tables. 04388 */ 04389 void /* PRIVATE */ 04390 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr) 04391 { 04392 png_uint_32 row_width = row_info->width; 04393 04394 png_debug(1, "in png_do_encode_alpha"); 04395 04396 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 04397 { 04398 if (row_info->bit_depth == 8) 04399 { 04400 PNG_CONST png_bytep table = png_ptr->gamma_from_1; 04401 04402 if (table != NULL) 04403 { 04404 PNG_CONST int step = 04405 (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; 04406 04407 /* The alpha channel is the last component: */ 04408 row += step - 1; 04409 04410 for (; row_width > 0; --row_width, row += step) 04411 *row = table[*row]; 04412 04413 return; 04414 } 04415 } 04416 04417 else if (row_info->bit_depth == 16) 04418 { 04419 PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; 04420 PNG_CONST int gamma_shift = png_ptr->gamma_shift; 04421 04422 if (table != NULL) 04423 { 04424 PNG_CONST int step = 04425 (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; 04426 04427 /* The alpha channel is the last component: */ 04428 row += step - 2; 04429 04430 for (; row_width > 0; --row_width, row += step) 04431 { 04432 png_uint_16 v; 04433 04434 v = table[*(row + 1) >> gamma_shift][*row]; 04435 *row = (png_byte)((v >> 8) & 0xff); 04436 *(row + 1) = (png_byte)(v & 0xff); 04437 } 04438 04439 return; 04440 } 04441 } 04442 } 04443 04444 /* Only get to here if called with a weird row_info; no harm has been done, 04445 * so just issue a warning. 04446 */ 04447 png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); 04448 } 04449 #endif 04450 04451 #ifdef PNG_READ_EXPAND_SUPPORTED 04452 /* Expands a palette row to an RGB or RGBA row depending 04453 * upon whether you supply trans and num_trans. 04454 */ 04455 void /* PRIVATE */ 04456 png_do_expand_palette(png_row_infop row_info, png_bytep row, 04457 png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) 04458 { 04459 int shift, value; 04460 png_bytep sp, dp; 04461 png_uint_32 i; 04462 png_uint_32 row_width=row_info->width; 04463 04464 png_debug(1, "in png_do_expand_palette"); 04465 04466 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) 04467 { 04468 if (row_info->bit_depth < 8) 04469 { 04470 switch (row_info->bit_depth) 04471 { 04472 case 1: 04473 { 04474 sp = row + (png_size_t)((row_width - 1) >> 3); 04475 dp = row + (png_size_t)row_width - 1; 04476 shift = 7 - (int)((row_width + 7) & 0x07); 04477 for (i = 0; i < row_width; i++) 04478 { 04479 if ((*sp >> shift) & 0x01) 04480 *dp = 1; 04481 04482 else 04483 *dp = 0; 04484 04485 if (shift == 7) 04486 { 04487 shift = 0; 04488 sp--; 04489 } 04490 04491 else 04492 shift++; 04493 04494 dp--; 04495 } 04496 break; 04497 } 04498 04499 case 2: 04500 { 04501 sp = row + (png_size_t)((row_width - 1) >> 2); 04502 dp = row + (png_size_t)row_width - 1; 04503 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 04504 for (i = 0; i < row_width; i++) 04505 { 04506 value = (*sp >> shift) & 0x03; 04507 *dp = (png_byte)value; 04508 if (shift == 6) 04509 { 04510 shift = 0; 04511 sp--; 04512 } 04513 04514 else 04515 shift += 2; 04516 04517 dp--; 04518 } 04519 break; 04520 } 04521 04522 case 4: 04523 { 04524 sp = row + (png_size_t)((row_width - 1) >> 1); 04525 dp = row + (png_size_t)row_width - 1; 04526 shift = (int)((row_width & 0x01) << 2); 04527 for (i = 0; i < row_width; i++) 04528 { 04529 value = (*sp >> shift) & 0x0f; 04530 *dp = (png_byte)value; 04531 if (shift == 4) 04532 { 04533 shift = 0; 04534 sp--; 04535 } 04536 04537 else 04538 shift += 4; 04539 04540 dp--; 04541 } 04542 break; 04543 } 04544 04545 default: 04546 break; 04547 } 04548 row_info->bit_depth = 8; 04549 row_info->pixel_depth = 8; 04550 row_info->rowbytes = row_width; 04551 } 04552 04553 if (row_info->bit_depth == 8) 04554 { 04555 { 04556 if (num_trans > 0) 04557 { 04558 sp = row + (png_size_t)row_width - 1; 04559 dp = row + (png_size_t)(row_width << 2) - 1; 04560 04561 for (i = 0; i < row_width; i++) 04562 { 04563 if ((int)(*sp) >= num_trans) 04564 *dp-- = 0xff; 04565 04566 else 04567 *dp-- = trans_alpha[*sp]; 04568 04569 *dp-- = palette[*sp].blue; 04570 *dp-- = palette[*sp].green; 04571 *dp-- = palette[*sp].red; 04572 sp--; 04573 } 04574 row_info->bit_depth = 8; 04575 row_info->pixel_depth = 32; 04576 row_info->rowbytes = row_width * 4; 04577 row_info->color_type = 6; 04578 row_info->channels = 4; 04579 } 04580 04581 else 04582 { 04583 sp = row + (png_size_t)row_width - 1; 04584 dp = row + (png_size_t)(row_width * 3) - 1; 04585 04586 for (i = 0; i < row_width; i++) 04587 { 04588 *dp-- = palette[*sp].blue; 04589 *dp-- = palette[*sp].green; 04590 *dp-- = palette[*sp].red; 04591 sp--; 04592 } 04593 04594 row_info->bit_depth = 8; 04595 row_info->pixel_depth = 24; 04596 row_info->rowbytes = row_width * 3; 04597 row_info->color_type = 2; 04598 row_info->channels = 3; 04599 } 04600 } 04601 } 04602 } 04603 } 04604 04605 /* If the bit depth < 8, it is expanded to 8. Also, if the already 04606 * expanded transparency value is supplied, an alpha channel is built. 04607 */ 04608 void /* PRIVATE */ 04609 png_do_expand(png_row_infop row_info, png_bytep row, 04610 png_const_color_16p trans_color) 04611 { 04612 int shift, value; 04613 png_bytep sp, dp; 04614 png_uint_32 i; 04615 png_uint_32 row_width=row_info->width; 04616 04617 png_debug(1, "in png_do_expand"); 04618 04619 { 04620 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 04621 { 04622 png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0); 04623 04624 if (row_info->bit_depth < 8) 04625 { 04626 switch (row_info->bit_depth) 04627 { 04628 case 1: 04629 { 04630 gray = (png_uint_16)((gray & 0x01) * 0xff); 04631 sp = row + (png_size_t)((row_width - 1) >> 3); 04632 dp = row + (png_size_t)row_width - 1; 04633 shift = 7 - (int)((row_width + 7) & 0x07); 04634 for (i = 0; i < row_width; i++) 04635 { 04636 if ((*sp >> shift) & 0x01) 04637 *dp = 0xff; 04638 04639 else 04640 *dp = 0; 04641 04642 if (shift == 7) 04643 { 04644 shift = 0; 04645 sp--; 04646 } 04647 04648 else 04649 shift++; 04650 04651 dp--; 04652 } 04653 break; 04654 } 04655 04656 case 2: 04657 { 04658 gray = (png_uint_16)((gray & 0x03) * 0x55); 04659 sp = row + (png_size_t)((row_width - 1) >> 2); 04660 dp = row + (png_size_t)row_width - 1; 04661 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 04662 for (i = 0; i < row_width; i++) 04663 { 04664 value = (*sp >> shift) & 0x03; 04665 *dp = (png_byte)(value | (value << 2) | (value << 4) | 04666 (value << 6)); 04667 if (shift == 6) 04668 { 04669 shift = 0; 04670 sp--; 04671 } 04672 04673 else 04674 shift += 2; 04675 04676 dp--; 04677 } 04678 break; 04679 } 04680 04681 case 4: 04682 { 04683 gray = (png_uint_16)((gray & 0x0f) * 0x11); 04684 sp = row + (png_size_t)((row_width - 1) >> 1); 04685 dp = row + (png_size_t)row_width - 1; 04686 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 04687 for (i = 0; i < row_width; i++) 04688 { 04689 value = (*sp >> shift) & 0x0f; 04690 *dp = (png_byte)(value | (value << 4)); 04691 if (shift == 4) 04692 { 04693 shift = 0; 04694 sp--; 04695 } 04696 04697 else 04698 shift = 4; 04699 04700 dp--; 04701 } 04702 break; 04703 } 04704 04705 default: 04706 break; 04707 } 04708 04709 row_info->bit_depth = 8; 04710 row_info->pixel_depth = 8; 04711 row_info->rowbytes = row_width; 04712 } 04713 04714 if (trans_color != NULL) 04715 { 04716 if (row_info->bit_depth == 8) 04717 { 04718 gray = gray & 0xff; 04719 sp = row + (png_size_t)row_width - 1; 04720 dp = row + (png_size_t)(row_width << 1) - 1; 04721 04722 for (i = 0; i < row_width; i++) 04723 { 04724 if (*sp == gray) 04725 *dp-- = 0; 04726 04727 else 04728 *dp-- = 0xff; 04729 04730 *dp-- = *sp--; 04731 } 04732 } 04733 04734 else if (row_info->bit_depth == 16) 04735 { 04736 png_byte gray_high = (png_byte)((gray >> 8) & 0xff); 04737 png_byte gray_low = (png_byte)(gray & 0xff); 04738 sp = row + row_info->rowbytes - 1; 04739 dp = row + (row_info->rowbytes << 1) - 1; 04740 for (i = 0; i < row_width; i++) 04741 { 04742 if (*(sp - 1) == gray_high && *(sp) == gray_low) 04743 { 04744 *dp-- = 0; 04745 *dp-- = 0; 04746 } 04747 04748 else 04749 { 04750 *dp-- = 0xff; 04751 *dp-- = 0xff; 04752 } 04753 04754 *dp-- = *sp--; 04755 *dp-- = *sp--; 04756 } 04757 } 04758 04759 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 04760 row_info->channels = 2; 04761 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 04762 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 04763 row_width); 04764 } 04765 } 04766 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) 04767 { 04768 if (row_info->bit_depth == 8) 04769 { 04770 png_byte red = (png_byte)(trans_color->red & 0xff); 04771 png_byte green = (png_byte)(trans_color->green & 0xff); 04772 png_byte blue = (png_byte)(trans_color->blue & 0xff); 04773 sp = row + (png_size_t)row_info->rowbytes - 1; 04774 dp = row + (png_size_t)(row_width << 2) - 1; 04775 for (i = 0; i < row_width; i++) 04776 { 04777 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 04778 *dp-- = 0; 04779 04780 else 04781 *dp-- = 0xff; 04782 04783 *dp-- = *sp--; 04784 *dp-- = *sp--; 04785 *dp-- = *sp--; 04786 } 04787 } 04788 else if (row_info->bit_depth == 16) 04789 { 04790 png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); 04791 png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); 04792 png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); 04793 png_byte red_low = (png_byte)(trans_color->red & 0xff); 04794 png_byte green_low = (png_byte)(trans_color->green & 0xff); 04795 png_byte blue_low = (png_byte)(trans_color->blue & 0xff); 04796 sp = row + row_info->rowbytes - 1; 04797 dp = row + (png_size_t)(row_width << 3) - 1; 04798 for (i = 0; i < row_width; i++) 04799 { 04800 if (*(sp - 5) == red_high && 04801 *(sp - 4) == red_low && 04802 *(sp - 3) == green_high && 04803 *(sp - 2) == green_low && 04804 *(sp - 1) == blue_high && 04805 *(sp ) == blue_low) 04806 { 04807 *dp-- = 0; 04808 *dp-- = 0; 04809 } 04810 04811 else 04812 { 04813 *dp-- = 0xff; 04814 *dp-- = 0xff; 04815 } 04816 04817 *dp-- = *sp--; 04818 *dp-- = *sp--; 04819 *dp-- = *sp--; 04820 *dp-- = *sp--; 04821 *dp-- = *sp--; 04822 *dp-- = *sp--; 04823 } 04824 } 04825 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 04826 row_info->channels = 4; 04827 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 04828 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 04829 } 04830 } 04831 } 04832 #endif 04833 04834 #ifdef PNG_READ_EXPAND_16_SUPPORTED 04835 /* If the bit depth is 8 and the color type is not a palette type expand the 04836 * whole row to 16 bits. Has no effect otherwise. 04837 */ 04838 void /* PRIVATE */ 04839 png_do_expand_16(png_row_infop row_info, png_bytep row) 04840 { 04841 if (row_info->bit_depth == 8 && 04842 row_info->color_type != PNG_COLOR_TYPE_PALETTE) 04843 { 04844 /* The row have a sequence of bytes containing [0..255] and we need 04845 * to turn it into another row containing [0..65535], to do this we 04846 * calculate: 04847 * 04848 * (input / 255) * 65535 04849 * 04850 * Which happens to be exactly input * 257 and this can be achieved 04851 * simply by byte replication in place (copying backwards). 04852 */ 04853 png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ 04854 png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ 04855 while (dp > sp) 04856 dp[-2] = dp[-1] = *--sp, dp -= 2; 04857 04858 row_info->rowbytes *= 2; 04859 row_info->bit_depth = 16; 04860 row_info->pixel_depth = (png_byte)(row_info->channels * 16); 04861 } 04862 } 04863 #endif 04864 04865 #ifdef PNG_READ_QUANTIZE_SUPPORTED 04866 void /* PRIVATE */ 04867 png_do_quantize(png_row_infop row_info, png_bytep row, 04868 png_const_bytep palette_lookup, png_const_bytep quantize_lookup) 04869 { 04870 png_bytep sp, dp; 04871 png_uint_32 i; 04872 png_uint_32 row_width=row_info->width; 04873 04874 png_debug(1, "in png_do_quantize"); 04875 04876 if (row_info->bit_depth == 8) 04877 { 04878 if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) 04879 { 04880 int r, g, b, p; 04881 sp = row; 04882 dp = row; 04883 for (i = 0; i < row_width; i++) 04884 { 04885 r = *sp++; 04886 g = *sp++; 04887 b = *sp++; 04888 04889 /* This looks real messy, but the compiler will reduce 04890 * it down to a reasonable formula. For example, with 04891 * 5 bits per color, we get: 04892 * p = (((r >> 3) & 0x1f) << 10) | 04893 * (((g >> 3) & 0x1f) << 5) | 04894 * ((b >> 3) & 0x1f); 04895 */ 04896 p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 04897 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 04898 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 04899 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 04900 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 04901 (PNG_QUANTIZE_BLUE_BITS)) | 04902 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 04903 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 04904 04905 *dp++ = palette_lookup[p]; 04906 } 04907 04908 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 04909 row_info->channels = 1; 04910 row_info->pixel_depth = row_info->bit_depth; 04911 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 04912 } 04913 04914 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 04915 palette_lookup != NULL) 04916 { 04917 int r, g, b, p; 04918 sp = row; 04919 dp = row; 04920 for (i = 0; i < row_width; i++) 04921 { 04922 r = *sp++; 04923 g = *sp++; 04924 b = *sp++; 04925 sp++; 04926 04927 p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & 04928 ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << 04929 (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | 04930 (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & 04931 ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << 04932 (PNG_QUANTIZE_BLUE_BITS)) | 04933 ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & 04934 ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); 04935 04936 *dp++ = palette_lookup[p]; 04937 } 04938 04939 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 04940 row_info->channels = 1; 04941 row_info->pixel_depth = row_info->bit_depth; 04942 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 04943 } 04944 04945 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 04946 quantize_lookup) 04947 { 04948 sp = row; 04949 04950 for (i = 0; i < row_width; i++, sp++) 04951 { 04952 *sp = quantize_lookup[*sp]; 04953 } 04954 } 04955 } 04956 } 04957 #endif /* PNG_READ_QUANTIZE_SUPPORTED */ 04958 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 04959 04960 #ifdef PNG_MNG_FEATURES_SUPPORTED 04961 /* Undoes intrapixel differencing */ 04962 void /* PRIVATE */ 04963 png_do_read_intrapixel(png_row_infop row_info, png_bytep row) 04964 { 04965 png_debug(1, "in png_do_read_intrapixel"); 04966 04967 if ( 04968 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 04969 { 04970 int bytes_per_pixel; 04971 png_uint_32 row_width = row_info->width; 04972 04973 if (row_info->bit_depth == 8) 04974 { 04975 png_bytep rp; 04976 png_uint_32 i; 04977 04978 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 04979 bytes_per_pixel = 3; 04980 04981 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 04982 bytes_per_pixel = 4; 04983 04984 else 04985 return; 04986 04987 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 04988 { 04989 *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); 04990 *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); 04991 } 04992 } 04993 else if (row_info->bit_depth == 16) 04994 { 04995 png_bytep rp; 04996 png_uint_32 i; 04997 04998 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 04999 bytes_per_pixel = 6; 05000 05001 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 05002 bytes_per_pixel = 8; 05003 05004 else 05005 return; 05006 05007 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 05008 { 05009 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 05010 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 05011 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 05012 png_uint_32 red = (s0 + s1 + 65536) & 0xffff; 05013 png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; 05014 *(rp ) = (png_byte)((red >> 8) & 0xff); 05015 *(rp + 1) = (png_byte)(red & 0xff); 05016 *(rp + 4) = (png_byte)((blue >> 8) & 0xff); 05017 *(rp + 5) = (png_byte)(blue & 0xff); 05018 } 05019 } 05020 } 05021 } 05022 #endif /* PNG_MNG_FEATURES_SUPPORTED */ 05023 #endif /* PNG_READ_SUPPORTED */ Generated on Fri May 25 2012 04:17:39 for ReactOS by
1.7.6.1
|