|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 00002 /* pngrtran.c - transforms the data in a row for PNG readers 00003 * 00004 * Last changed in libpng 1.2.38 [July 16, 2009] 00005 * Copyright (c) 1998-2009 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 #define PNG_INTERNAL 00020 #include "png.h" 00021 #if defined(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 /* Tell libpng how we react to CRC errors in critical chunks */ 00029 if (png_ptr == NULL) 00030 return; 00031 switch (crit_action) 00032 { 00033 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 00034 break; 00035 00036 case PNG_CRC_WARN_USE: /* Warn/use data */ 00037 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00038 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 00039 break; 00040 00041 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 00042 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00043 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 00044 PNG_FLAG_CRC_CRITICAL_IGNORE; 00045 break; 00046 00047 case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ 00048 png_warning(png_ptr, 00049 "Can't discard critical data on CRC error."); 00050 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 00051 00052 case PNG_CRC_DEFAULT: 00053 default: 00054 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 00055 break; 00056 } 00057 00058 switch (ancil_action) 00059 { 00060 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 00061 break; 00062 00063 case PNG_CRC_WARN_USE: /* Warn/use data */ 00064 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00065 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 00066 break; 00067 00068 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 00069 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00070 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 00071 PNG_FLAG_CRC_ANCILLARY_NOWARN; 00072 break; 00073 00074 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 00075 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00076 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 00077 break; 00078 00079 case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ 00080 00081 case PNG_CRC_DEFAULT: 00082 default: 00083 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 00084 break; 00085 } 00086 } 00087 00088 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 00089 defined(PNG_FLOATING_POINT_SUPPORTED) 00090 /* Handle alpha and tRNS via a background color */ 00091 void PNGAPI 00092 png_set_background(png_structp png_ptr, 00093 png_color_16p background_color, int background_gamma_code, 00094 int need_expand, double background_gamma) 00095 { 00096 png_debug(1, "in png_set_background"); 00097 if (png_ptr == NULL) 00098 return; 00099 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 00100 { 00101 png_warning(png_ptr, "Application must supply a known background gamma"); 00102 return; 00103 } 00104 00105 png_ptr->transformations |= PNG_BACKGROUND; 00106 png_memcpy(&(png_ptr->background), background_color, 00107 png_sizeof(png_color_16)); 00108 png_ptr->background_gamma = (float)background_gamma; 00109 png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 00110 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); 00111 } 00112 #endif 00113 00114 #if defined(PNG_READ_16_TO_8_SUPPORTED) 00115 /* Strip 16 bit depth files to 8 bit depth */ 00116 void PNGAPI 00117 png_set_strip_16(png_structp png_ptr) 00118 { 00119 png_debug(1, "in png_set_strip_16"); 00120 if (png_ptr == NULL) 00121 return; 00122 png_ptr->transformations |= PNG_16_TO_8; 00123 } 00124 #endif 00125 00126 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 00127 void PNGAPI 00128 png_set_strip_alpha(png_structp png_ptr) 00129 { 00130 png_debug(1, "in png_set_strip_alpha"); 00131 if (png_ptr == NULL) 00132 return; 00133 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; 00134 } 00135 #endif 00136 00137 #if defined(PNG_READ_DITHER_SUPPORTED) 00138 /* Dither file to 8 bit. Supply a palette, the current number 00139 * of elements in the palette, the maximum number of elements 00140 * allowed, and a histogram if possible. If the current number 00141 * of colors is greater then the maximum number, the palette will be 00142 * modified to fit in the maximum number. "full_dither" indicates 00143 * whether we need a dithering cube set up for RGB images, or if we 00144 * simply are reducing the number of colors in a paletted image. 00145 */ 00146 00147 typedef struct png_dsort_struct 00148 { 00149 struct png_dsort_struct FAR * next; 00150 png_byte left; 00151 png_byte right; 00152 } png_dsort; 00153 typedef png_dsort FAR * png_dsortp; 00154 typedef png_dsort FAR * FAR * png_dsortpp; 00155 00156 void PNGAPI 00157 png_set_dither(png_structp png_ptr, png_colorp palette, 00158 int num_palette, int maximum_colors, png_uint_16p histogram, 00159 int full_dither) 00160 { 00161 png_debug(1, "in png_set_dither"); 00162 if (png_ptr == NULL) 00163 return; 00164 png_ptr->transformations |= PNG_DITHER; 00165 00166 if (!full_dither) 00167 { 00168 int i; 00169 00170 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, 00171 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00172 for (i = 0; i < num_palette; i++) 00173 png_ptr->dither_index[i] = (png_byte)i; 00174 } 00175 00176 if (num_palette > maximum_colors) 00177 { 00178 if (histogram != NULL) 00179 { 00180 /* This is easy enough, just throw out the least used colors. 00181 * Perhaps not the best solution, but good enough. 00182 */ 00183 00184 int i; 00185 00186 /* Initialize an array to sort colors */ 00187 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, 00188 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00189 00190 /* Initialize the dither_sort array */ 00191 for (i = 0; i < num_palette; i++) 00192 png_ptr->dither_sort[i] = (png_byte)i; 00193 00194 /* Find the least used palette entries by starting a 00195 * bubble sort, and running it until we have sorted 00196 * out enough colors. Note that we don't care about 00197 * sorting all the colors, just finding which are 00198 * least used. 00199 */ 00200 00201 for (i = num_palette - 1; i >= maximum_colors; i--) 00202 { 00203 int done; /* To stop early if the list is pre-sorted */ 00204 int j; 00205 00206 done = 1; 00207 for (j = 0; j < i; j++) 00208 { 00209 if (histogram[png_ptr->dither_sort[j]] 00210 < histogram[png_ptr->dither_sort[j + 1]]) 00211 { 00212 png_byte t; 00213 00214 t = png_ptr->dither_sort[j]; 00215 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; 00216 png_ptr->dither_sort[j + 1] = t; 00217 done = 0; 00218 } 00219 } 00220 if (done) 00221 break; 00222 } 00223 00224 /* Swap the palette around, and set up a table, if necessary */ 00225 if (full_dither) 00226 { 00227 int j = num_palette; 00228 00229 /* Put all the useful colors within the max, but don't 00230 * move the others. 00231 */ 00232 for (i = 0; i < maximum_colors; i++) 00233 { 00234 if ((int)png_ptr->dither_sort[i] >= maximum_colors) 00235 { 00236 do 00237 j--; 00238 while ((int)png_ptr->dither_sort[j] >= maximum_colors); 00239 palette[i] = palette[j]; 00240 } 00241 } 00242 } 00243 else 00244 { 00245 int j = num_palette; 00246 00247 /* Move all the used colors inside the max limit, and 00248 * develop a translation table. 00249 */ 00250 for (i = 0; i < maximum_colors; i++) 00251 { 00252 /* Only move the colors we need to */ 00253 if ((int)png_ptr->dither_sort[i] >= maximum_colors) 00254 { 00255 png_color tmp_color; 00256 00257 do 00258 j--; 00259 while ((int)png_ptr->dither_sort[j] >= maximum_colors); 00260 00261 tmp_color = palette[j]; 00262 palette[j] = palette[i]; 00263 palette[i] = tmp_color; 00264 /* Indicate where the color went */ 00265 png_ptr->dither_index[j] = (png_byte)i; 00266 png_ptr->dither_index[i] = (png_byte)j; 00267 } 00268 } 00269 00270 /* Find closest color for those colors we are not using */ 00271 for (i = 0; i < num_palette; i++) 00272 { 00273 if ((int)png_ptr->dither_index[i] >= maximum_colors) 00274 { 00275 int min_d, k, min_k, d_index; 00276 00277 /* Find the closest color to one we threw out */ 00278 d_index = png_ptr->dither_index[i]; 00279 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 00280 for (k = 1, min_k = 0; k < maximum_colors; k++) 00281 { 00282 int d; 00283 00284 d = PNG_COLOR_DIST(palette[d_index], palette[k]); 00285 00286 if (d < min_d) 00287 { 00288 min_d = d; 00289 min_k = k; 00290 } 00291 } 00292 /* Point to closest color */ 00293 png_ptr->dither_index[i] = (png_byte)min_k; 00294 } 00295 } 00296 } 00297 png_free(png_ptr, png_ptr->dither_sort); 00298 png_ptr->dither_sort = NULL; 00299 } 00300 else 00301 { 00302 /* This is much harder to do simply (and quickly). Perhaps 00303 * we need to go through a median cut routine, but those 00304 * don't always behave themselves with only a few colors 00305 * as input. So we will just find the closest two colors, 00306 * and throw out one of them (chosen somewhat randomly). 00307 * [We don't understand this at all, so if someone wants to 00308 * work on improving it, be our guest - AED, GRP] 00309 */ 00310 int i; 00311 int max_d; 00312 int num_new_palette; 00313 png_dsortp t; 00314 png_dsortpp hash; 00315 00316 t = NULL; 00317 00318 /* Initialize palette index arrays */ 00319 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 00320 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00321 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 00322 (png_uint_32)(num_palette * png_sizeof(png_byte))); 00323 00324 /* Initialize the sort array */ 00325 for (i = 0; i < num_palette; i++) 00326 { 00327 png_ptr->index_to_palette[i] = (png_byte)i; 00328 png_ptr->palette_to_index[i] = (png_byte)i; 00329 } 00330 00331 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * 00332 png_sizeof(png_dsortp))); 00333 png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); 00334 00335 num_new_palette = num_palette; 00336 00337 /* Initial wild guess at how far apart the farthest pixel 00338 * pair we will be eliminating will be. Larger 00339 * numbers mean more areas will be allocated, Smaller 00340 * numbers run the risk of not saving enough data, and 00341 * having to do this all over again. 00342 * 00343 * I have not done extensive checking on this number. 00344 */ 00345 max_d = 96; 00346 00347 while (num_new_palette > maximum_colors) 00348 { 00349 for (i = 0; i < num_new_palette - 1; i++) 00350 { 00351 int j; 00352 00353 for (j = i + 1; j < num_new_palette; j++) 00354 { 00355 int d; 00356 00357 d = PNG_COLOR_DIST(palette[i], palette[j]); 00358 00359 if (d <= max_d) 00360 { 00361 00362 t = (png_dsortp)png_malloc_warn(png_ptr, 00363 (png_uint_32)(png_sizeof(png_dsort))); 00364 if (t == NULL) 00365 break; 00366 t->next = hash[d]; 00367 t->left = (png_byte)i; 00368 t->right = (png_byte)j; 00369 hash[d] = t; 00370 } 00371 } 00372 if (t == NULL) 00373 break; 00374 } 00375 00376 if (t != NULL) 00377 for (i = 0; i <= max_d; i++) 00378 { 00379 if (hash[i] != NULL) 00380 { 00381 png_dsortp p; 00382 00383 for (p = hash[i]; p; p = p->next) 00384 { 00385 if ((int)png_ptr->index_to_palette[p->left] 00386 < num_new_palette && 00387 (int)png_ptr->index_to_palette[p->right] 00388 < num_new_palette) 00389 { 00390 int j, next_j; 00391 00392 if (num_new_palette & 0x01) 00393 { 00394 j = p->left; 00395 next_j = p->right; 00396 } 00397 else 00398 { 00399 j = p->right; 00400 next_j = p->left; 00401 } 00402 00403 num_new_palette--; 00404 palette[png_ptr->index_to_palette[j]] 00405 = palette[num_new_palette]; 00406 if (!full_dither) 00407 { 00408 int k; 00409 00410 for (k = 0; k < num_palette; k++) 00411 { 00412 if (png_ptr->dither_index[k] == 00413 png_ptr->index_to_palette[j]) 00414 png_ptr->dither_index[k] = 00415 png_ptr->index_to_palette[next_j]; 00416 if ((int)png_ptr->dither_index[k] == 00417 num_new_palette) 00418 png_ptr->dither_index[k] = 00419 png_ptr->index_to_palette[j]; 00420 } 00421 } 00422 00423 png_ptr->index_to_palette[png_ptr->palette_to_index 00424 [num_new_palette]] = png_ptr->index_to_palette[j]; 00425 png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 00426 = png_ptr->palette_to_index[num_new_palette]; 00427 00428 png_ptr->index_to_palette[j] = (png_byte)num_new_palette; 00429 png_ptr->palette_to_index[num_new_palette] = (png_byte)j; 00430 } 00431 if (num_new_palette <= maximum_colors) 00432 break; 00433 } 00434 if (num_new_palette <= maximum_colors) 00435 break; 00436 } 00437 } 00438 00439 for (i = 0; i < 769; i++) 00440 { 00441 if (hash[i] != NULL) 00442 { 00443 png_dsortp p = hash[i]; 00444 while (p) 00445 { 00446 t = p->next; 00447 png_free(png_ptr, p); 00448 p = t; 00449 } 00450 } 00451 hash[i] = 0; 00452 } 00453 max_d += 96; 00454 } 00455 png_free(png_ptr, hash); 00456 png_free(png_ptr, png_ptr->palette_to_index); 00457 png_free(png_ptr, png_ptr->index_to_palette); 00458 png_ptr->palette_to_index = NULL; 00459 png_ptr->index_to_palette = NULL; 00460 } 00461 num_palette = maximum_colors; 00462 } 00463 if (png_ptr->palette == NULL) 00464 { 00465 png_ptr->palette = palette; 00466 } 00467 png_ptr->num_palette = (png_uint_16)num_palette; 00468 00469 if (full_dither) 00470 { 00471 int i; 00472 png_bytep distance; 00473 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + 00474 PNG_DITHER_BLUE_BITS; 00475 int num_red = (1 << PNG_DITHER_RED_BITS); 00476 int num_green = (1 << PNG_DITHER_GREEN_BITS); 00477 int num_blue = (1 << PNG_DITHER_BLUE_BITS); 00478 png_size_t num_entries = ((png_size_t)1 << total_bits); 00479 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, 00480 (png_uint_32)(num_entries * png_sizeof(png_byte))); 00481 png_memset(png_ptr->palette_lookup, 0, num_entries * 00482 png_sizeof(png_byte)); 00483 00484 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 00485 png_sizeof(png_byte))); 00486 00487 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); 00488 00489 for (i = 0; i < num_palette; i++) 00490 { 00491 int ir, ig, ib; 00492 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); 00493 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); 00494 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); 00495 00496 for (ir = 0; ir < num_red; ir++) 00497 { 00498 /* int dr = abs(ir - r); */ 00499 int dr = ((ir > r) ? ir - r : r - ir); 00500 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); 00501 00502 for (ig = 0; ig < num_green; ig++) 00503 { 00504 /* int dg = abs(ig - g); */ 00505 int dg = ((ig > g) ? ig - g : g - ig); 00506 int dt = dr + dg; 00507 int dm = ((dr > dg) ? dr : dg); 00508 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); 00509 00510 for (ib = 0; ib < num_blue; ib++) 00511 { 00512 int d_index = index_g | ib; 00513 /* int db = abs(ib - b); */ 00514 int db = ((ib > b) ? ib - b : b - ib); 00515 int dmax = ((dm > db) ? dm : db); 00516 int d = dmax + dt + db; 00517 00518 if (d < (int)distance[d_index]) 00519 { 00520 distance[d_index] = (png_byte)d; 00521 png_ptr->palette_lookup[d_index] = (png_byte)i; 00522 } 00523 } 00524 } 00525 } 00526 } 00527 00528 png_free(png_ptr, distance); 00529 } 00530 } 00531 #endif 00532 00533 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 00534 /* Transform the image from the file_gamma to the screen_gamma. We 00535 * only do transformations on images where the file_gamma and screen_gamma 00536 * are not close reciprocals, otherwise it slows things down slightly, and 00537 * also needlessly introduces small errors. 00538 * 00539 * We will turn off gamma transformation later if no semitransparent entries 00540 * are present in the tRNS array for palette images. We can't do it here 00541 * because we don't necessarily have the tRNS chunk yet. 00542 */ 00543 void PNGAPI 00544 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) 00545 { 00546 png_debug(1, "in png_set_gamma"); 00547 if (png_ptr == NULL) 00548 return; 00549 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || 00550 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || 00551 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 00552 png_ptr->transformations |= PNG_GAMMA; 00553 png_ptr->gamma = (float)file_gamma; 00554 png_ptr->screen_gamma = (float)scrn_gamma; 00555 } 00556 #endif 00557 00558 #if defined(PNG_READ_EXPAND_SUPPORTED) 00559 /* Expand paletted images to RGB, expand grayscale images of 00560 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 00561 * to alpha channels. 00562 */ 00563 void PNGAPI 00564 png_set_expand(png_structp png_ptr) 00565 { 00566 png_debug(1, "in png_set_expand"); 00567 if (png_ptr == NULL) 00568 return; 00569 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00570 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00571 } 00572 00573 /* GRR 19990627: the following three functions currently are identical 00574 * to png_set_expand(). However, it is entirely reasonable that someone 00575 * might wish to expand an indexed image to RGB but *not* expand a single, 00576 * fully transparent palette entry to a full alpha channel--perhaps instead 00577 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 00578 * the transparent color with a particular RGB value, or drop tRNS entirely. 00579 * IOW, a future version of the library may make the transformations flag 00580 * a bit more fine-grained, with separate bits for each of these three 00581 * functions. 00582 * 00583 * More to the point, these functions make it obvious what libpng will be 00584 * doing, whereas "expand" can (and does) mean any number of things. 00585 * 00586 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified 00587 * to expand only the sample depth but not to expand the tRNS to alpha. 00588 */ 00589 00590 /* Expand paletted images to RGB. */ 00591 void PNGAPI 00592 png_set_palette_to_rgb(png_structp png_ptr) 00593 { 00594 png_debug(1, "in png_set_palette_to_rgb"); 00595 if (png_ptr == NULL) 00596 return; 00597 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00598 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00599 } 00600 00601 #if !defined(PNG_1_0_X) 00602 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 00603 void PNGAPI 00604 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) 00605 { 00606 png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); 00607 if (png_ptr == NULL) 00608 return; 00609 png_ptr->transformations |= PNG_EXPAND; 00610 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00611 } 00612 #endif 00613 00614 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) 00615 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 00616 /* Deprecated as of libpng-1.2.9 */ 00617 void PNGAPI 00618 png_set_gray_1_2_4_to_8(png_structp png_ptr) 00619 { 00620 png_debug(1, "in png_set_gray_1_2_4_to_8"); 00621 if (png_ptr == NULL) 00622 return; 00623 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00624 } 00625 #endif 00626 00627 00628 /* Expand tRNS chunks to alpha channels. */ 00629 void PNGAPI 00630 png_set_tRNS_to_alpha(png_structp png_ptr) 00631 { 00632 png_debug(1, "in png_set_tRNS_to_alpha"); 00633 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 00634 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00635 } 00636 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ 00637 00638 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 00639 void PNGAPI 00640 png_set_gray_to_rgb(png_structp png_ptr) 00641 { 00642 png_debug(1, "in png_set_gray_to_rgb"); 00643 png_ptr->transformations |= PNG_GRAY_TO_RGB; 00644 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 00645 } 00646 #endif 00647 00648 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 00649 #if defined(PNG_FLOATING_POINT_SUPPORTED) 00650 /* Convert a RGB image to a grayscale of the same width. This allows us, 00651 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 00652 */ 00653 00654 void PNGAPI 00655 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, 00656 double green) 00657 { 00658 int red_fixed = (int)((float)red*100000.0 + 0.5); 00659 int green_fixed = (int)((float)green*100000.0 + 0.5); 00660 if (png_ptr == NULL) 00661 return; 00662 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); 00663 } 00664 #endif 00665 00666 void PNGAPI 00667 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, 00668 png_fixed_point red, png_fixed_point green) 00669 { 00670 png_debug(1, "in png_set_rgb_to_gray"); 00671 if (png_ptr == NULL) 00672 return; 00673 switch(error_action) 00674 { 00675 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; 00676 break; 00677 00678 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 00679 break; 00680 00681 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 00682 } 00683 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 00684 #if defined(PNG_READ_EXPAND_SUPPORTED) 00685 png_ptr->transformations |= PNG_EXPAND; 00686 #else 00687 { 00688 png_warning(png_ptr, 00689 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); 00690 png_ptr->transformations &= ~PNG_RGB_TO_GRAY; 00691 } 00692 #endif 00693 { 00694 png_uint_16 red_int, green_int; 00695 if (red < 0 || green < 0) 00696 { 00697 red_int = 6968; /* .212671 * 32768 + .5 */ 00698 green_int = 23434; /* .715160 * 32768 + .5 */ 00699 } 00700 else if (red + green < 100000L) 00701 { 00702 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); 00703 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); 00704 } 00705 else 00706 { 00707 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); 00708 red_int = 6968; 00709 green_int = 23434; 00710 } 00711 png_ptr->rgb_to_gray_red_coeff = red_int; 00712 png_ptr->rgb_to_gray_green_coeff = green_int; 00713 png_ptr->rgb_to_gray_blue_coeff = 00714 (png_uint_16)(32768 - red_int - green_int); 00715 } 00716 } 00717 #endif 00718 00719 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 00720 defined(PNG_LEGACY_SUPPORTED) || \ 00721 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 00722 void PNGAPI 00723 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr 00724 read_user_transform_fn) 00725 { 00726 png_debug(1, "in png_set_read_user_transform_fn"); 00727 if (png_ptr == NULL) 00728 return; 00729 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 00730 png_ptr->transformations |= PNG_USER_TRANSFORM; 00731 png_ptr->read_user_transform_fn = read_user_transform_fn; 00732 #endif 00733 #ifdef PNG_LEGACY_SUPPORTED 00734 if (read_user_transform_fn) 00735 png_warning(png_ptr, 00736 "This version of libpng does not support user transforms"); 00737 #endif 00738 } 00739 #endif 00740 00741 /* Initialize everything needed for the read. This includes modifying 00742 * the palette. 00743 */ 00744 void /* PRIVATE */ 00745 png_init_read_transformations(png_structp png_ptr) 00746 { 00747 png_debug(1, "in png_init_read_transformations"); 00748 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00749 if (png_ptr != NULL) 00750 #endif 00751 { 00752 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ 00753 || defined(PNG_READ_GAMMA_SUPPORTED) 00754 int color_type = png_ptr->color_type; 00755 #endif 00756 00757 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 00758 00759 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 00760 /* Detect gray background and attempt to enable optimization 00761 * for gray --> RGB case 00762 * 00763 * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 00764 * RGB_ALPHA (in which case need_expand is superfluous anyway), the 00765 * background color might actually be gray yet not be flagged as such. 00766 * This is not a problem for the current code, which uses 00767 * PNG_BACKGROUND_IS_GRAY only to decide when to do the 00768 * png_do_gray_to_rgb() transformation. 00769 */ 00770 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 00771 !(color_type & PNG_COLOR_MASK_COLOR)) 00772 { 00773 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 00774 } else if ((png_ptr->transformations & PNG_BACKGROUND) && 00775 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 00776 (png_ptr->transformations & PNG_GRAY_TO_RGB) && 00777 png_ptr->background.red == png_ptr->background.green && 00778 png_ptr->background.red == png_ptr->background.blue) 00779 { 00780 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 00781 png_ptr->background.gray = png_ptr->background.red; 00782 } 00783 #endif 00784 00785 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 00786 (png_ptr->transformations & PNG_EXPAND)) 00787 { 00788 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ 00789 { 00790 /* Expand background and tRNS chunks */ 00791 switch (png_ptr->bit_depth) 00792 { 00793 case 1: 00794 png_ptr->background.gray *= (png_uint_16)0xff; 00795 png_ptr->background.red = png_ptr->background.green 00796 = png_ptr->background.blue = png_ptr->background.gray; 00797 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 00798 { 00799 png_ptr->trans_values.gray *= (png_uint_16)0xff; 00800 png_ptr->trans_values.red = png_ptr->trans_values.green 00801 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 00802 } 00803 break; 00804 00805 case 2: 00806 png_ptr->background.gray *= (png_uint_16)0x55; 00807 png_ptr->background.red = png_ptr->background.green 00808 = png_ptr->background.blue = png_ptr->background.gray; 00809 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 00810 { 00811 png_ptr->trans_values.gray *= (png_uint_16)0x55; 00812 png_ptr->trans_values.red = png_ptr->trans_values.green 00813 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 00814 } 00815 break; 00816 00817 case 4: 00818 png_ptr->background.gray *= (png_uint_16)0x11; 00819 png_ptr->background.red = png_ptr->background.green 00820 = png_ptr->background.blue = png_ptr->background.gray; 00821 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 00822 { 00823 png_ptr->trans_values.gray *= (png_uint_16)0x11; 00824 png_ptr->trans_values.red = png_ptr->trans_values.green 00825 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 00826 } 00827 break; 00828 00829 case 8: 00830 00831 case 16: 00832 png_ptr->background.red = png_ptr->background.green 00833 = png_ptr->background.blue = png_ptr->background.gray; 00834 break; 00835 } 00836 } 00837 else if (color_type == PNG_COLOR_TYPE_PALETTE) 00838 { 00839 png_ptr->background.red = 00840 png_ptr->palette[png_ptr->background.index].red; 00841 png_ptr->background.green = 00842 png_ptr->palette[png_ptr->background.index].green; 00843 png_ptr->background.blue = 00844 png_ptr->palette[png_ptr->background.index].blue; 00845 00846 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 00847 if (png_ptr->transformations & PNG_INVERT_ALPHA) 00848 { 00849 #if defined(PNG_READ_EXPAND_SUPPORTED) 00850 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 00851 #endif 00852 { 00853 /* Invert the alpha channel (in tRNS) unless the pixels are 00854 * going to be expanded, in which case leave it for later 00855 */ 00856 int i, istop; 00857 istop=(int)png_ptr->num_trans; 00858 for (i=0; i<istop; i++) 00859 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); 00860 } 00861 } 00862 #endif 00863 00864 } 00865 } 00866 #endif 00867 00868 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) 00869 png_ptr->background_1 = png_ptr->background; 00870 #endif 00871 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 00872 00873 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) 00874 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) 00875 < PNG_GAMMA_THRESHOLD)) 00876 { 00877 int i, k; 00878 k=0; 00879 for (i=0; i<png_ptr->num_trans; i++) 00880 { 00881 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) 00882 k=1; /* Partial transparency is present */ 00883 } 00884 if (k == 0) 00885 png_ptr->transformations &= ~PNG_GAMMA; 00886 } 00887 00888 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && 00889 png_ptr->gamma != 0.0) 00890 { 00891 png_build_gamma_table(png_ptr); 00892 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 00893 if (png_ptr->transformations & PNG_BACKGROUND) 00894 { 00895 if (color_type == PNG_COLOR_TYPE_PALETTE) 00896 { 00897 /* Could skip if no transparency */ 00898 png_color back, back_1; 00899 png_colorp palette = png_ptr->palette; 00900 int num_palette = png_ptr->num_palette; 00901 int i; 00902 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 00903 { 00904 back.red = png_ptr->gamma_table[png_ptr->background.red]; 00905 back.green = png_ptr->gamma_table[png_ptr->background.green]; 00906 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 00907 00908 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 00909 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 00910 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 00911 } 00912 else 00913 { 00914 double g, gs; 00915 00916 switch (png_ptr->background_gamma_type) 00917 { 00918 case PNG_BACKGROUND_GAMMA_SCREEN: 00919 g = (png_ptr->screen_gamma); 00920 gs = 1.0; 00921 break; 00922 00923 case PNG_BACKGROUND_GAMMA_FILE: 00924 g = 1.0 / (png_ptr->gamma); 00925 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 00926 break; 00927 00928 case PNG_BACKGROUND_GAMMA_UNIQUE: 00929 g = 1.0 / (png_ptr->background_gamma); 00930 gs = 1.0 / (png_ptr->background_gamma * 00931 png_ptr->screen_gamma); 00932 break; 00933 default: 00934 g = 1.0; /* back_1 */ 00935 gs = 1.0; /* back */ 00936 } 00937 00938 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) 00939 { 00940 back.red = (png_byte)png_ptr->background.red; 00941 back.green = (png_byte)png_ptr->background.green; 00942 back.blue = (png_byte)png_ptr->background.blue; 00943 } 00944 else 00945 { 00946 back.red = (png_byte)(pow( 00947 (double)png_ptr->background.red/255, gs) * 255.0 + .5); 00948 back.green = (png_byte)(pow( 00949 (double)png_ptr->background.green/255, gs) * 255.0 + .5); 00950 back.blue = (png_byte)(pow( 00951 (double)png_ptr->background.blue/255, gs) * 255.0 + .5); 00952 } 00953 00954 back_1.red = (png_byte)(pow( 00955 (double)png_ptr->background.red/255, g) * 255.0 + .5); 00956 back_1.green = (png_byte)(pow( 00957 (double)png_ptr->background.green/255, g) * 255.0 + .5); 00958 back_1.blue = (png_byte)(pow( 00959 (double)png_ptr->background.blue/255, g) * 255.0 + .5); 00960 } 00961 for (i = 0; i < num_palette; i++) 00962 { 00963 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) 00964 { 00965 if (png_ptr->trans[i] == 0) 00966 { 00967 palette[i] = back; 00968 } 00969 else /* if (png_ptr->trans[i] != 0xff) */ 00970 { 00971 png_byte v, w; 00972 00973 v = png_ptr->gamma_to_1[palette[i].red]; 00974 png_composite(w, v, png_ptr->trans[i], back_1.red); 00975 palette[i].red = png_ptr->gamma_from_1[w]; 00976 00977 v = png_ptr->gamma_to_1[palette[i].green]; 00978 png_composite(w, v, png_ptr->trans[i], back_1.green); 00979 palette[i].green = png_ptr->gamma_from_1[w]; 00980 00981 v = png_ptr->gamma_to_1[palette[i].blue]; 00982 png_composite(w, v, png_ptr->trans[i], back_1.blue); 00983 palette[i].blue = png_ptr->gamma_from_1[w]; 00984 } 00985 } 00986 else 00987 { 00988 palette[i].red = png_ptr->gamma_table[palette[i].red]; 00989 palette[i].green = png_ptr->gamma_table[palette[i].green]; 00990 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 00991 } 00992 } 00993 /* Prevent the transformations being done again, and make sure 00994 * that the now spurious alpha channel is stripped - the code 00995 * has just reduced background composition and gamma correction 00996 * to a simple alpha channel strip. 00997 */ 00998 png_ptr->transformations &= ~PNG_BACKGROUND; 00999 png_ptr->transformations &= ~PNG_GAMMA; 01000 png_ptr->transformations |= PNG_STRIP_ALPHA; 01001 } 01002 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 01003 else 01004 /* color_type != PNG_COLOR_TYPE_PALETTE */ 01005 { 01006 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); 01007 double g = 1.0; 01008 double gs = 1.0; 01009 01010 switch (png_ptr->background_gamma_type) 01011 { 01012 case PNG_BACKGROUND_GAMMA_SCREEN: 01013 g = (png_ptr->screen_gamma); 01014 gs = 1.0; 01015 break; 01016 01017 case PNG_BACKGROUND_GAMMA_FILE: 01018 g = 1.0 / (png_ptr->gamma); 01019 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 01020 break; 01021 01022 case PNG_BACKGROUND_GAMMA_UNIQUE: 01023 g = 1.0 / (png_ptr->background_gamma); 01024 gs = 1.0 / (png_ptr->background_gamma * 01025 png_ptr->screen_gamma); 01026 break; 01027 } 01028 01029 png_ptr->background_1.gray = (png_uint_16)(pow( 01030 (double)png_ptr->background.gray / m, g) * m + .5); 01031 png_ptr->background.gray = (png_uint_16)(pow( 01032 (double)png_ptr->background.gray / m, gs) * m + .5); 01033 01034 if ((png_ptr->background.red != png_ptr->background.green) || 01035 (png_ptr->background.red != png_ptr->background.blue) || 01036 (png_ptr->background.red != png_ptr->background.gray)) 01037 { 01038 /* RGB or RGBA with color background */ 01039 png_ptr->background_1.red = (png_uint_16)(pow( 01040 (double)png_ptr->background.red / m, g) * m + .5); 01041 png_ptr->background_1.green = (png_uint_16)(pow( 01042 (double)png_ptr->background.green / m, g) * m + .5); 01043 png_ptr->background_1.blue = (png_uint_16)(pow( 01044 (double)png_ptr->background.blue / m, g) * m + .5); 01045 png_ptr->background.red = (png_uint_16)(pow( 01046 (double)png_ptr->background.red / m, gs) * m + .5); 01047 png_ptr->background.green = (png_uint_16)(pow( 01048 (double)png_ptr->background.green / m, gs) * m + .5); 01049 png_ptr->background.blue = (png_uint_16)(pow( 01050 (double)png_ptr->background.blue / m, gs) * m + .5); 01051 } 01052 else 01053 { 01054 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 01055 png_ptr->background_1.red = png_ptr->background_1.green 01056 = png_ptr->background_1.blue = png_ptr->background_1.gray; 01057 png_ptr->background.red = png_ptr->background.green 01058 = png_ptr->background.blue = png_ptr->background.gray; 01059 } 01060 } 01061 } 01062 else 01063 /* Transformation does not include PNG_BACKGROUND */ 01064 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 01065 if (color_type == PNG_COLOR_TYPE_PALETTE) 01066 { 01067 png_colorp palette = png_ptr->palette; 01068 int num_palette = png_ptr->num_palette; 01069 int i; 01070 01071 for (i = 0; i < num_palette; i++) 01072 { 01073 palette[i].red = png_ptr->gamma_table[palette[i].red]; 01074 palette[i].green = png_ptr->gamma_table[palette[i].green]; 01075 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 01076 } 01077 01078 /* Done the gamma correction. */ 01079 png_ptr->transformations &= ~PNG_GAMMA; 01080 } 01081 } 01082 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 01083 else 01084 #endif 01085 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ 01086 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 01087 /* No GAMMA transformation */ 01088 if ((png_ptr->transformations & PNG_BACKGROUND) && 01089 (color_type == PNG_COLOR_TYPE_PALETTE)) 01090 { 01091 int i; 01092 int istop = (int)png_ptr->num_trans; 01093 png_color back; 01094 png_colorp palette = png_ptr->palette; 01095 01096 back.red = (png_byte)png_ptr->background.red; 01097 back.green = (png_byte)png_ptr->background.green; 01098 back.blue = (png_byte)png_ptr->background.blue; 01099 01100 for (i = 0; i < istop; i++) 01101 { 01102 if (png_ptr->trans[i] == 0) 01103 { 01104 palette[i] = back; 01105 } 01106 else if (png_ptr->trans[i] != 0xff) 01107 { 01108 /* The png_composite() macro is defined in png.h */ 01109 png_composite(palette[i].red, palette[i].red, 01110 png_ptr->trans[i], back.red); 01111 png_composite(palette[i].green, palette[i].green, 01112 png_ptr->trans[i], back.green); 01113 png_composite(palette[i].blue, palette[i].blue, 01114 png_ptr->trans[i], back.blue); 01115 } 01116 } 01117 01118 /* Handled alpha, still need to strip the channel. */ 01119 png_ptr->transformations &= ~PNG_BACKGROUND; 01120 png_ptr->transformations |= PNG_STRIP_ALPHA; 01121 } 01122 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 01123 01124 #if defined(PNG_READ_SHIFT_SUPPORTED) 01125 if ((png_ptr->transformations & PNG_SHIFT) && 01126 (color_type == PNG_COLOR_TYPE_PALETTE)) 01127 { 01128 png_uint_16 i; 01129 png_uint_16 istop = png_ptr->num_palette; 01130 int sr = 8 - png_ptr->sig_bit.red; 01131 int sg = 8 - png_ptr->sig_bit.green; 01132 int sb = 8 - png_ptr->sig_bit.blue; 01133 01134 if (sr < 0 || sr > 8) 01135 sr = 0; 01136 if (sg < 0 || sg > 8) 01137 sg = 0; 01138 if (sb < 0 || sb > 8) 01139 sb = 0; 01140 for (i = 0; i < istop; i++) 01141 { 01142 png_ptr->palette[i].red >>= sr; 01143 png_ptr->palette[i].green >>= sg; 01144 png_ptr->palette[i].blue >>= sb; 01145 } 01146 } 01147 #endif /* PNG_READ_SHIFT_SUPPORTED */ 01148 } 01149 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ 01150 && !defined(PNG_READ_BACKGROUND_SUPPORTED) 01151 if (png_ptr) 01152 return; 01153 #endif 01154 } 01155 01156 /* Modify the info structure to reflect the transformations. The 01157 * info should be updated so a PNG file could be written with it, 01158 * assuming the transformations result in valid PNG data. 01159 */ 01160 void /* PRIVATE */ 01161 png_read_transform_info(png_structp png_ptr, png_infop info_ptr) 01162 { 01163 png_debug(1, "in png_read_transform_info"); 01164 #if defined(PNG_READ_EXPAND_SUPPORTED) 01165 if (png_ptr->transformations & PNG_EXPAND) 01166 { 01167 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01168 { 01169 if (png_ptr->num_trans && 01170 (png_ptr->transformations & PNG_EXPAND_tRNS)) 01171 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 01172 else 01173 info_ptr->color_type = PNG_COLOR_TYPE_RGB; 01174 info_ptr->bit_depth = 8; 01175 info_ptr->num_trans = 0; 01176 } 01177 else 01178 { 01179 if (png_ptr->num_trans) 01180 { 01181 if (png_ptr->transformations & PNG_EXPAND_tRNS) 01182 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 01183 } 01184 if (info_ptr->bit_depth < 8) 01185 info_ptr->bit_depth = 8; 01186 info_ptr->num_trans = 0; 01187 } 01188 } 01189 #endif 01190 01191 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 01192 if (png_ptr->transformations & PNG_BACKGROUND) 01193 { 01194 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 01195 info_ptr->num_trans = 0; 01196 info_ptr->background = png_ptr->background; 01197 } 01198 #endif 01199 01200 #if defined(PNG_READ_GAMMA_SUPPORTED) 01201 if (png_ptr->transformations & PNG_GAMMA) 01202 { 01203 #ifdef PNG_FLOATING_POINT_SUPPORTED 01204 info_ptr->gamma = png_ptr->gamma; 01205 #endif 01206 #ifdef PNG_FIXED_POINT_SUPPORTED 01207 info_ptr->int_gamma = png_ptr->int_gamma; 01208 #endif 01209 } 01210 #endif 01211 01212 #if defined(PNG_READ_16_TO_8_SUPPORTED) 01213 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) 01214 info_ptr->bit_depth = 8; 01215 #endif 01216 01217 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 01218 if (png_ptr->transformations & PNG_GRAY_TO_RGB) 01219 info_ptr->color_type |= PNG_COLOR_MASK_COLOR; 01220 #endif 01221 01222 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 01223 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 01224 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; 01225 #endif 01226 01227 #if defined(PNG_READ_DITHER_SUPPORTED) 01228 if (png_ptr->transformations & PNG_DITHER) 01229 { 01230 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 01231 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 01232 png_ptr->palette_lookup && info_ptr->bit_depth == 8) 01233 { 01234 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 01235 } 01236 } 01237 #endif 01238 01239 #if defined(PNG_READ_PACK_SUPPORTED) 01240 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) 01241 info_ptr->bit_depth = 8; 01242 #endif 01243 01244 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 01245 info_ptr->channels = 1; 01246 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 01247 info_ptr->channels = 3; 01248 else 01249 info_ptr->channels = 1; 01250 01251 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 01252 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 01253 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 01254 #endif 01255 01256 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 01257 info_ptr->channels++; 01258 01259 #if defined(PNG_READ_FILLER_SUPPORTED) 01260 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 01261 if ((png_ptr->transformations & PNG_FILLER) && 01262 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 01263 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) 01264 { 01265 info_ptr->channels++; 01266 /* If adding a true alpha channel not just filler */ 01267 #if !defined(PNG_1_0_X) 01268 if (png_ptr->transformations & PNG_ADD_ALPHA) 01269 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 01270 #endif 01271 } 01272 #endif 01273 01274 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 01275 defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 01276 if (png_ptr->transformations & PNG_USER_TRANSFORM) 01277 { 01278 if (info_ptr->bit_depth < png_ptr->user_transform_depth) 01279 info_ptr->bit_depth = png_ptr->user_transform_depth; 01280 if (info_ptr->channels < png_ptr->user_transform_channels) 01281 info_ptr->channels = png_ptr->user_transform_channels; 01282 } 01283 #endif 01284 01285 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 01286 info_ptr->bit_depth); 01287 01288 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 01289 01290 #if !defined(PNG_READ_EXPAND_SUPPORTED) 01291 if (png_ptr) 01292 return; 01293 #endif 01294 } 01295 01296 /* Transform the row. The order of transformations is significant, 01297 * and is very touchy. If you add a transformation, take care to 01298 * decide how it fits in with the other transformations here. 01299 */ 01300 void /* PRIVATE */ 01301 png_do_read_transformations(png_structp png_ptr) 01302 { 01303 png_debug(1, "in png_do_read_transformations"); 01304 if (png_ptr->row_buf == NULL) 01305 { 01306 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 01307 char msg[50]; 01308 01309 png_snprintf2(msg, 50, 01310 "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, 01311 png_ptr->pass); 01312 png_error(png_ptr, msg); 01313 #else 01314 png_error(png_ptr, "NULL row buffer"); 01315 #endif 01316 } 01317 #ifdef PNG_WARN_UNINITIALIZED_ROW 01318 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 01319 /* Application has failed to call either png_read_start_image() 01320 * or png_read_update_info() after setting transforms that expand 01321 * pixels. This check added to libpng-1.2.19 01322 */ 01323 #if (PNG_WARN_UNINITIALIZED_ROW==1) 01324 png_error(png_ptr, "Uninitialized row"); 01325 #else 01326 png_warning(png_ptr, "Uninitialized row"); 01327 #endif 01328 #endif 01329 01330 #if defined(PNG_READ_EXPAND_SUPPORTED) 01331 if (png_ptr->transformations & PNG_EXPAND) 01332 { 01333 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) 01334 { 01335 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, 01336 png_ptr->palette, png_ptr->trans, png_ptr->num_trans); 01337 } 01338 else 01339 { 01340 if (png_ptr->num_trans && 01341 (png_ptr->transformations & PNG_EXPAND_tRNS)) 01342 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 01343 &(png_ptr->trans_values)); 01344 else 01345 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 01346 NULL); 01347 } 01348 } 01349 #endif 01350 01351 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 01352 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 01353 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 01354 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); 01355 #endif 01356 01357 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 01358 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 01359 { 01360 int rgb_error = 01361 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); 01362 if (rgb_error) 01363 { 01364 png_ptr->rgb_to_gray_status=1; 01365 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 01366 PNG_RGB_TO_GRAY_WARN) 01367 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 01368 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 01369 PNG_RGB_TO_GRAY_ERR) 01370 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 01371 } 01372 } 01373 #endif 01374 01375 /* From Andreas Dilger e-mail to png-implement, 26 March 1998: 01376 * 01377 * In most cases, the "simple transparency" should be done prior to doing 01378 * gray-to-RGB, or you will have to test 3x as many bytes to check if a 01379 * pixel is transparent. You would also need to make sure that the 01380 * transparency information is upgraded to RGB. 01381 * 01382 * To summarize, the current flow is: 01383 * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 01384 * with background "in place" if transparent, 01385 * convert to RGB if necessary 01386 * - Gray + alpha -> composite with gray background and remove alpha bytes, 01387 * convert to RGB if necessary 01388 * 01389 * To support RGB backgrounds for gray images we need: 01390 * - Gray + simple transparency -> convert to RGB + simple transparency, 01391 * compare 3 or 6 bytes and composite with 01392 * background "in place" if transparent 01393 * (3x compare/pixel compared to doing 01394 * composite with gray bkgrnd) 01395 * - Gray + alpha -> convert to RGB + alpha, composite with background and 01396 * remove alpha bytes (3x float 01397 * operations/pixel compared with composite 01398 * on gray background) 01399 * 01400 * Greg's change will do this. The reason it wasn't done before is for 01401 * performance, as this increases the per-pixel operations. If we would check 01402 * in advance if the background was gray or RGB, and position the gray-to-RGB 01403 * transform appropriately, then it would save a lot of work/time. 01404 */ 01405 01406 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 01407 /* If gray -> RGB, do so now only if background is non-gray; else do later 01408 * for performance reasons 01409 */ 01410 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 01411 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 01412 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 01413 #endif 01414 01415 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 01416 if ((png_ptr->transformations & PNG_BACKGROUND) && 01417 ((png_ptr->num_trans != 0 ) || 01418 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) 01419 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, 01420 &(png_ptr->trans_values), &(png_ptr->background) 01421 #if defined(PNG_READ_GAMMA_SUPPORTED) 01422 , &(png_ptr->background_1), 01423 png_ptr->gamma_table, png_ptr->gamma_from_1, 01424 png_ptr->gamma_to_1, png_ptr->gamma_16_table, 01425 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, 01426 png_ptr->gamma_shift 01427 #endif 01428 ); 01429 #endif 01430 01431 #if defined(PNG_READ_GAMMA_SUPPORTED) 01432 if ((png_ptr->transformations & PNG_GAMMA) && 01433 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 01434 !((png_ptr->transformations & PNG_BACKGROUND) && 01435 ((png_ptr->num_trans != 0) || 01436 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && 01437 #endif 01438 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 01439 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, 01440 png_ptr->gamma_table, png_ptr->gamma_16_table, 01441 png_ptr->gamma_shift); 01442 #endif 01443 01444 #if defined(PNG_READ_16_TO_8_SUPPORTED) 01445 if (png_ptr->transformations & PNG_16_TO_8) 01446 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); 01447 #endif 01448 01449 #if defined(PNG_READ_DITHER_SUPPORTED) 01450 if (png_ptr->transformations & PNG_DITHER) 01451 { 01452 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, 01453 png_ptr->palette_lookup, png_ptr->dither_index); 01454 if (png_ptr->row_info.rowbytes == (png_uint_32)0) 01455 png_error(png_ptr, "png_do_dither returned rowbytes=0"); 01456 } 01457 #endif 01458 01459 #if defined(PNG_READ_INVERT_SUPPORTED) 01460 if (png_ptr->transformations & PNG_INVERT_MONO) 01461 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); 01462 #endif 01463 01464 #if defined(PNG_READ_SHIFT_SUPPORTED) 01465 if (png_ptr->transformations & PNG_SHIFT) 01466 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, 01467 &(png_ptr->shift)); 01468 #endif 01469 01470 #if defined(PNG_READ_PACK_SUPPORTED) 01471 if (png_ptr->transformations & PNG_PACK) 01472 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); 01473 #endif 01474 01475 #if defined(PNG_READ_BGR_SUPPORTED) 01476 if (png_ptr->transformations & PNG_BGR) 01477 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); 01478 #endif 01479 01480 #if defined(PNG_READ_PACKSWAP_SUPPORTED) 01481 if (png_ptr->transformations & PNG_PACKSWAP) 01482 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); 01483 #endif 01484 01485 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 01486 /* If gray -> RGB, do so now only if we did not do so above */ 01487 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 01488 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 01489 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 01490 #endif 01491 01492 #if defined(PNG_READ_FILLER_SUPPORTED) 01493 if (png_ptr->transformations & PNG_FILLER) 01494 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 01495 (png_uint_32)png_ptr->filler, png_ptr->flags); 01496 #endif 01497 01498 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 01499 if (png_ptr->transformations & PNG_INVERT_ALPHA) 01500 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 01501 #endif 01502 01503 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) 01504 if (png_ptr->transformations & PNG_SWAP_ALPHA) 01505 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 01506 #endif 01507 01508 #if defined(PNG_READ_SWAP_SUPPORTED) 01509 if (png_ptr->transformations & PNG_SWAP_BYTES) 01510 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); 01511 #endif 01512 01513 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 01514 if (png_ptr->transformations & PNG_USER_TRANSFORM) 01515 { 01516 if (png_ptr->read_user_transform_fn != NULL) 01517 (*(png_ptr->read_user_transform_fn)) /* User read transform function */ 01518 (png_ptr, /* png_ptr */ 01519 &(png_ptr->row_info), /* row_info: */ 01520 /* png_uint_32 width; width of row */ 01521 /* png_uint_32 rowbytes; number of bytes in row */ 01522 /* png_byte color_type; color type of pixels */ 01523 /* png_byte bit_depth; bit depth of samples */ 01524 /* png_byte channels; number of channels (1-4) */ 01525 /* png_byte pixel_depth; bits per pixel (depth*channels) */ 01526 png_ptr->row_buf + 1); /* start of pixel data for row */ 01527 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) 01528 if (png_ptr->user_transform_depth) 01529 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; 01530 if (png_ptr->user_transform_channels) 01531 png_ptr->row_info.channels = png_ptr->user_transform_channels; 01532 #endif 01533 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * 01534 png_ptr->row_info.channels); 01535 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, 01536 png_ptr->row_info.width); 01537 } 01538 #endif 01539 01540 } 01541 01542 #if defined(PNG_READ_PACK_SUPPORTED) 01543 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 01544 * without changing the actual values. Thus, if you had a row with 01545 * a bit depth of 1, you would end up with bytes that only contained 01546 * the numbers 0 or 1. If you would rather they contain 0 and 255, use 01547 * png_do_shift() after this. 01548 */ 01549 void /* PRIVATE */ 01550 png_do_unpack(png_row_infop row_info, png_bytep row) 01551 { 01552 png_debug(1, "in png_do_unpack"); 01553 #if defined(PNG_USELESS_TESTS_SUPPORTED) 01554 if (row != NULL && row_info != NULL && row_info->bit_depth < 8) 01555 #else 01556 if (row_info->bit_depth < 8) 01557 #endif 01558 { 01559 png_uint_32 i; 01560 png_uint_32 row_width=row_info->width; 01561 01562 switch (row_info->bit_depth) 01563 { 01564 case 1: 01565 { 01566 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 01567 png_bytep dp = row + (png_size_t)row_width - 1; 01568 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); 01569 for (i = 0; i < row_width; i++) 01570 { 01571 *dp = (png_byte)((*sp >> shift) & 0x01); 01572 if (shift == 7) 01573 { 01574 shift = 0; 01575 sp--; 01576 } 01577 else 01578 shift++; 01579 01580 dp--; 01581 } 01582 break; 01583 } 01584 01585 case 2: 01586 { 01587 01588 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 01589 png_bytep dp = row + (png_size_t)row_width - 1; 01590 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 01591 for (i = 0; i < row_width; i++) 01592 { 01593 *dp = (png_byte)((*sp >> shift) & 0x03); 01594 if (shift == 6) 01595 { 01596 shift = 0; 01597 sp--; 01598 } 01599 else 01600 shift += 2; 01601 01602 dp--; 01603 } 01604 break; 01605 } 01606 01607 case 4: 01608 { 01609 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 01610 png_bytep dp = row + (png_size_t)row_width - 1; 01611 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 01612 for (i = 0; i < row_width; i++) 01613 { 01614 *dp = (png_byte)((*sp >> shift) & 0x0f); 01615 if (shift == 4) 01616 { 01617 shift = 0; 01618 sp--; 01619 } 01620 else 01621 shift = 4; 01622 01623 dp--; 01624 } 01625 break; 01626 } 01627 } 01628 row_info->bit_depth = 8; 01629 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 01630 row_info->rowbytes = row_width * row_info->channels; 01631 } 01632 } 01633 #endif 01634 01635 #if defined(PNG_READ_SHIFT_SUPPORTED) 01636 /* Reverse the effects of png_do_shift. This routine merely shifts the 01637 * pixels back to their significant bits values. Thus, if you have 01638 * a row of bit depth 8, but only 5 are significant, this will shift 01639 * the values back to 0 through 31. 01640 */ 01641 void /* PRIVATE */ 01642 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) 01643 { 01644 png_debug(1, "in png_do_unshift"); 01645 if ( 01646 #if defined(PNG_USELESS_TESTS_SUPPORTED) 01647 row != NULL && row_info != NULL && sig_bits != NULL && 01648 #endif 01649 row_info->color_type != PNG_COLOR_TYPE_PALETTE) 01650 { 01651 int shift[4]; 01652 int channels = 0; 01653 int c; 01654 png_uint_16 value = 0; 01655 png_uint_32 row_width = row_info->width; 01656 01657 if (row_info->color_type & PNG_COLOR_MASK_COLOR) 01658 { 01659 shift[channels++] = row_info->bit_depth - sig_bits->red; 01660 shift[channels++] = row_info->bit_depth - sig_bits->green; 01661 shift[channels++] = row_info->bit_depth - sig_bits->blue; 01662 } 01663 else 01664 { 01665 shift[channels++] = row_info->bit_depth - sig_bits->gray; 01666 } 01667 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 01668 { 01669 shift[channels++] = row_info->bit_depth - sig_bits->alpha; 01670 } 01671 01672 for (c = 0; c < channels; c++) 01673 { 01674 if (shift[c] <= 0) 01675 shift[c] = 0; 01676 else 01677 value = 1; 01678 } 01679 01680 if (!value) 01681 return; 01682 01683 switch (row_info->bit_depth) 01684 { 01685 case 2: 01686 { 01687 png_bytep bp; 01688 png_uint_32 i; 01689 png_uint_32 istop = row_info->rowbytes; 01690 01691 for (bp = row, i = 0; i < istop; i++) 01692 { 01693 *bp >>= 1; 01694 *bp++ &= 0x55; 01695 } 01696 break; 01697 } 01698 01699 case 4: 01700 { 01701 png_bytep bp = row; 01702 png_uint_32 i; 01703 png_uint_32 istop = row_info->rowbytes; 01704 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | 01705 (png_byte)((int)0xf >> shift[0])); 01706 01707 for (i = 0; i < istop; i++) 01708 { 01709 *bp >>= shift[0]; 01710 *bp++ &= mask; 01711 } 01712 break; 01713 } 01714 01715 case 8: 01716 { 01717 png_bytep bp = row; 01718 png_uint_32 i; 01719 png_uint_32 istop = row_width * channels; 01720 01721 for (i = 0; i < istop; i++) 01722 { 01723 *bp++ >>= shift[i%channels]; 01724 } 01725 break; 01726 } 01727 01728 case 16: 01729 { 01730 png_bytep bp = row; 01731 png_uint_32 i; 01732 png_uint_32 istop = channels * row_width; 01733 01734 for (i = 0; i < istop; i++) 01735 { 01736 value = (png_uint_16)((*bp << 8) + *(bp + 1)); 01737 value >>= shift[i%channels]; 01738 *bp++ = (png_byte)(value >> 8); 01739 *bp++ = (png_byte)(value & 0xff); 01740 } 01741 break; 01742 } 01743 } 01744 } 01745 } 01746 #endif 01747 01748 #if defined(PNG_READ_16_TO_8_SUPPORTED) 01749 /* Chop rows of bit depth 16 down to 8 */ 01750 void /* PRIVATE */ 01751 png_do_chop(png_row_infop row_info, png_bytep row) 01752 { 01753 png_debug(1, "in png_do_chop"); 01754 #if defined(PNG_USELESS_TESTS_SUPPORTED) 01755 if (row != NULL && row_info != NULL && row_info->bit_depth == 16) 01756 #else 01757 if (row_info->bit_depth == 16) 01758 #endif 01759 { 01760 png_bytep sp = row; 01761 png_bytep dp = row; 01762 png_uint_32 i; 01763 png_uint_32 istop = row_info->width * row_info->channels; 01764 01765 for (i = 0; i<istop; i++, sp += 2, dp++) 01766 { 01767 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED) 01768 /* This does a more accurate scaling of the 16-bit color 01769 * value, rather than a simple low-byte truncation. 01770 * 01771 * What the ideal calculation should be: 01772 * *dp = (((((png_uint_32)(*sp) << 8) | 01773 * (png_uint_32)(*(sp + 1))) * 255 + 127) 01774 * / (png_uint_32)65535L; 01775 * 01776 * GRR: no, I think this is what it really should be: 01777 * *dp = (((((png_uint_32)(*sp) << 8) | 01778 * (png_uint_32)(*(sp + 1))) + 128L) 01779 * / (png_uint_32)257L; 01780 * 01781 * GRR: here's the exact calculation with shifts: 01782 * temp = (((png_uint_32)(*sp) << 8) | 01783 * (png_uint_32)(*(sp + 1))) + 128L; 01784 * *dp = (temp - (temp >> 8)) >> 8; 01785 * 01786 * Approximate calculation with shift/add instead of multiply/divide: 01787 * *dp = ((((png_uint_32)(*sp) << 8) | 01788 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; 01789 * 01790 * What we actually do to avoid extra shifting and conversion: 01791 */ 01792 01793 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); 01794 #else 01795 /* Simply discard the low order byte */ 01796 *dp = *sp; 01797 #endif 01798 } 01799 row_info->bit_depth = 8; 01800 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 01801 row_info->rowbytes = row_info->width * row_info->channels; 01802 } 01803 } 01804 #endif 01805 01806 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) 01807 void /* PRIVATE */ 01808 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 01809 { 01810 png_debug(1, "in png_do_read_swap_alpha"); 01811 #if defined(PNG_USELESS_TESTS_SUPPORTED) 01812 if (row != NULL && row_info != NULL) 01813 #endif 01814 { 01815 png_uint_32 row_width = row_info->width; 01816 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 01817 { 01818 /* This converts from RGBA to ARGB */ 01819 if (row_info->bit_depth == 8) 01820 { 01821 png_bytep sp = row + row_info->rowbytes; 01822 png_bytep dp = sp; 01823 png_byte save; 01824 png_uint_32 i; 01825 01826 for (i = 0; i < row_width; i++) 01827 { 01828 save = *(--sp); 01829 *(--dp) = *(--sp); 01830 *(--dp) = *(--sp); 01831 *(--dp) = *(--sp); 01832 *(--dp) = save; 01833 } 01834 } 01835 /* This converts from RRGGBBAA to AARRGGBB */ 01836 else 01837 { 01838 png_bytep sp = row + row_info->rowbytes; 01839 png_bytep dp = sp; 01840 png_byte save[2]; 01841 png_uint_32 i; 01842 01843 for (i = 0; i < row_width; i++) 01844 { 01845 save[0] = *(--sp); 01846 save[1] = *(--sp); 01847 *(--dp) = *(--sp); 01848 *(--dp) = *(--sp); 01849 *(--dp) = *(--sp); 01850 *(--dp) = *(--sp); 01851 *(--dp) = *(--sp); 01852 *(--dp) = *(--sp); 01853 *(--dp) = save[0]; 01854 *(--dp) = save[1]; 01855 } 01856 } 01857 } 01858 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 01859 { 01860 /* This converts from GA to AG */ 01861 if (row_info->bit_depth == 8) 01862 { 01863 png_bytep sp = row + row_info->rowbytes; 01864 png_bytep dp = sp; 01865 png_byte save; 01866 png_uint_32 i; 01867 01868 for (i = 0; i < row_width; i++) 01869 { 01870 save = *(--sp); 01871 *(--dp) = *(--sp); 01872 *(--dp) = save; 01873 } 01874 } 01875 /* This converts from GGAA to AAGG */ 01876 else 01877 { 01878 png_bytep sp = row + row_info->rowbytes; 01879 png_bytep dp = sp; 01880 png_byte save[2]; 01881 png_uint_32 i; 01882 01883 for (i = 0; i < row_width; i++) 01884 { 01885 save[0] = *(--sp); 01886 save[1] = *(--sp); 01887 *(--dp) = *(--sp); 01888 *(--dp) = *(--sp); 01889 *(--dp) = save[0]; 01890 *(--dp) = save[1]; 01891 } 01892 } 01893 } 01894 } 01895 } 01896 #endif 01897 01898 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 01899 void /* PRIVATE */ 01900 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 01901 { 01902 png_debug(1, "in png_do_read_invert_alpha"); 01903 #if defined(PNG_USELESS_TESTS_SUPPORTED) 01904 if (row != NULL && row_info != NULL) 01905 #endif 01906 { 01907 png_uint_32 row_width = row_info->width; 01908 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 01909 { 01910 /* This inverts the alpha channel in RGBA */ 01911 if (row_info->bit_depth == 8) 01912 { 01913 png_bytep sp = row + row_info->rowbytes; 01914 png_bytep dp = sp; 01915 png_uint_32 i; 01916 01917 for (i = 0; i < row_width; i++) 01918 { 01919 *(--dp) = (png_byte)(255 - *(--sp)); 01920 01921 /* This does nothing: 01922 *(--dp) = *(--sp); 01923 *(--dp) = *(--sp); 01924 *(--dp) = *(--sp); 01925 We can replace it with: 01926 */ 01927 sp-=3; 01928 dp=sp; 01929 } 01930 } 01931 /* This inverts the alpha channel in RRGGBBAA */ 01932 else 01933 { 01934 png_bytep sp = row + row_info->rowbytes; 01935 png_bytep dp = sp; 01936 png_uint_32 i; 01937 01938 for (i = 0; i < row_width; i++) 01939 { 01940 *(--dp) = (png_byte)(255 - *(--sp)); 01941 *(--dp) = (png_byte)(255 - *(--sp)); 01942 01943 /* This does nothing: 01944 *(--dp) = *(--sp); 01945 *(--dp) = *(--sp); 01946 *(--dp) = *(--sp); 01947 *(--dp) = *(--sp); 01948 *(--dp) = *(--sp); 01949 *(--dp) = *(--sp); 01950 We can replace it with: 01951 */ 01952 sp-=6; 01953 dp=sp; 01954 } 01955 } 01956 } 01957 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 01958 { 01959 /* This inverts the alpha channel in GA */ 01960 if (row_info->bit_depth == 8) 01961 { 01962 png_bytep sp = row + row_info->rowbytes; 01963 png_bytep dp = sp; 01964 png_uint_32 i; 01965 01966 for (i = 0; i < row_width; i++) 01967 { 01968 *(--dp) = (png_byte)(255 - *(--sp)); 01969 *(--dp) = *(--sp); 01970 } 01971 } 01972 /* This inverts the alpha channel in GGAA */ 01973 else 01974 { 01975 png_bytep sp = row + row_info->rowbytes; 01976 png_bytep dp = sp; 01977 png_uint_32 i; 01978 01979 for (i = 0; i < row_width; i++) 01980 { 01981 *(--dp) = (png_byte)(255 - *(--sp)); 01982 *(--dp) = (png_byte)(255 - *(--sp)); 01983 /* 01984 *(--dp) = *(--sp); 01985 *(--dp) = *(--sp); 01986 */ 01987 sp-=2; 01988 dp=sp; 01989 } 01990 } 01991 } 01992 } 01993 } 01994 #endif 01995 01996 #if defined(PNG_READ_FILLER_SUPPORTED) 01997 /* Add filler channel if we have RGB color */ 01998 void /* PRIVATE */ 01999 png_do_read_filler(png_row_infop row_info, png_bytep row, 02000 png_uint_32 filler, png_uint_32 flags) 02001 { 02002 png_uint_32 i; 02003 png_uint_32 row_width = row_info->width; 02004 02005 png_byte hi_filler = (png_byte)((filler>>8) & 0xff); 02006 png_byte lo_filler = (png_byte)(filler & 0xff); 02007 02008 png_debug(1, "in png_do_read_filler"); 02009 if ( 02010 #if defined(PNG_USELESS_TESTS_SUPPORTED) 02011 row != NULL && row_info != NULL && 02012 #endif 02013 row_info->color_type == PNG_COLOR_TYPE_GRAY) 02014 { 02015 if (row_info->bit_depth == 8) 02016 { 02017 /* This changes the data from G to GX */ 02018 if (flags & PNG_FLAG_FILLER_AFTER) 02019 { 02020 png_bytep sp = row + (png_size_t)row_width; 02021 png_bytep dp = sp + (png_size_t)row_width; 02022 for (i = 1; i < row_width; i++) 02023 { 02024 *(--dp) = lo_filler; 02025 *(--dp) = *(--sp); 02026 } 02027 *(--dp) = lo_filler; 02028 row_info->channels = 2; 02029 row_info->pixel_depth = 16; 02030 row_info->rowbytes = row_width * 2; 02031 } 02032 /* This changes the data from G to XG */ 02033 else 02034 { 02035 png_bytep sp = row + (png_size_t)row_width; 02036 png_bytep dp = sp + (png_size_t)row_width; 02037 for (i = 0; i < row_width; i++) 02038 { 02039 *(--dp) = *(--sp); 02040 *(--dp) = lo_filler; 02041 } 02042 row_info->channels = 2; 02043 row_info->pixel_depth = 16; 02044 row_info->rowbytes = row_width * 2; 02045 } 02046 } 02047 else if (row_info->bit_depth == 16) 02048 { 02049 /* This changes the data from GG to GGXX */ 02050 if (flags & PNG_FLAG_FILLER_AFTER) 02051 { 02052 png_bytep sp = row + (png_size_t)row_width * 2; 02053 png_bytep dp = sp + (png_size_t)row_width * 2; 02054 for (i = 1; i < row_width; i++) 02055 { 02056 *(--dp) = hi_filler; 02057 *(--dp) = lo_filler; 02058 *(--dp) = *(--sp); 02059 *(--dp) = *(--sp); 02060 } 02061 *(--dp) = hi_filler; 02062 *(--dp) = lo_filler; 02063 row_info->channels = 2; 02064 row_info->pixel_depth = 32; 02065 row_info->rowbytes = row_width * 4; 02066 } 02067 /* This changes the data from GG to XXGG */ 02068 else 02069 { 02070 png_bytep sp = row + (png_size_t)row_width * 2; 02071 png_bytep dp = sp + (png_size_t)row_width * 2; 02072 for (i = 0; i < row_width; i++) 02073 { 02074 *(--dp) = *(--sp); 02075 *(--dp) = *(--sp); 02076 *(--dp) = hi_filler; 02077 *(--dp) = lo_filler; 02078 } 02079 row_info->channels = 2; 02080 row_info->pixel_depth = 32; 02081 row_info->rowbytes = row_width * 4; 02082 } 02083 } 02084 } /* COLOR_TYPE == GRAY */ 02085 else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 02086 { 02087 if (row_info->bit_depth == 8) 02088 { 02089 /* This changes the data from RGB to RGBX */ 02090 if (flags & PNG_FLAG_FILLER_AFTER) 02091 { 02092 png_bytep sp = row + (png_size_t)row_width * 3; 02093 png_bytep dp = sp + (png_size_t)row_width; 02094 for (i = 1; i < row_width; i++) 02095 { 02096 *(--dp) = lo_filler; 02097 *(--dp) = *(--sp); 02098 *(--dp) = *(--sp); 02099 *(--dp) = *(--sp); 02100 } 02101 *(--dp) = lo_filler; 02102 row_info->channels = 4; 02103 row_info->pixel_depth = 32; 02104 row_info->rowbytes = row_width * 4; 02105 } 02106 /* This changes the data from RGB to XRGB */ 02107 else 02108 { 02109 png_bytep sp = row + (png_size_t)row_width * 3; 02110 png_bytep dp = sp + (png_size_t)row_width; 02111 for (i = 0; i < row_width; i++) 02112 { 02113 *(--dp) = *(--sp); 02114 *(--dp) = *(--sp); 02115 *(--dp) = *(--sp); 02116 *(--dp) = lo_filler; 02117 } 02118 row_info->channels = 4; 02119 row_info->pixel_depth = 32; 02120 row_info->rowbytes = row_width * 4; 02121 } 02122 } 02123 else if (row_info->bit_depth == 16) 02124 { 02125 /* This changes the data from RRGGBB to RRGGBBXX */ 02126 if (flags & PNG_FLAG_FILLER_AFTER) 02127 { 02128 png_bytep sp = row + (png_size_t)row_width * 6; 02129 png_bytep dp = sp + (png_size_t)row_width * 2; 02130 for (i = 1; i < row_width; i++) 02131 { 02132 *(--dp) = hi_filler; 02133 *(--dp) = lo_filler; 02134 *(--dp) = *(--sp); 02135 *(--dp) = *(--sp); 02136 *(--dp) = *(--sp); 02137 *(--dp) = *(--sp); 02138 *(--dp) = *(--sp); 02139 *(--dp) = *(--sp); 02140 } 02141 *(--dp) = hi_filler; 02142 *(--dp) = lo_filler; 02143 row_info->channels = 4; 02144 row_info->pixel_depth = 64; 02145 row_info->rowbytes = row_width * 8; 02146 } 02147 /* This changes the data from RRGGBB to XXRRGGBB */ 02148 else 02149 { 02150 png_bytep sp = row + (png_size_t)row_width * 6; 02151 png_bytep dp = sp + (png_size_t)row_width * 2; 02152 for (i = 0; i < row_width; i++) 02153 { 02154 *(--dp) = *(--sp); 02155 *(--dp) = *(--sp); 02156 *(--dp) = *(--sp); 02157 *(--dp) = *(--sp); 02158 *(--dp) = *(--sp); 02159 *(--dp) = *(--sp); 02160 *(--dp) = hi_filler; 02161 *(--dp) = lo_filler; 02162 } 02163 row_info->channels = 4; 02164 row_info->pixel_depth = 64; 02165 row_info->rowbytes = row_width * 8; 02166 } 02167 } 02168 } /* COLOR_TYPE == RGB */ 02169 } 02170 #endif 02171 02172 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 02173 /* Expand grayscale files to RGB, with or without alpha */ 02174 void /* PRIVATE */ 02175 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 02176 { 02177 png_uint_32 i; 02178 png_uint_32 row_width = row_info->width; 02179 02180 png_debug(1, "in png_do_gray_to_rgb"); 02181 if (row_info->bit_depth >= 8 && 02182 #if defined(PNG_USELESS_TESTS_SUPPORTED) 02183 row != NULL && row_info != NULL && 02184 #endif 02185 !(row_info->color_type & PNG_COLOR_MASK_COLOR)) 02186 { 02187 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 02188 { 02189 if (row_info->bit_depth == 8) 02190 { 02191 png_bytep sp = row + (png_size_t)row_width - 1; 02192 png_bytep dp = sp + (png_size_t)row_width * 2; 02193 for (i = 0; i < row_width; i++) 02194 { 02195 *(dp--) = *sp; 02196 *(dp--) = *sp; 02197 *(dp--) = *(sp--); 02198 } 02199 } 02200 else 02201 { 02202 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 02203 png_bytep dp = sp + (png_size_t)row_width * 4; 02204 for (i = 0; i < row_width; i++) 02205 { 02206 *(dp--) = *sp; 02207 *(dp--) = *(sp - 1); 02208 *(dp--) = *sp; 02209 *(dp--) = *(sp - 1); 02210 *(dp--) = *(sp--); 02211 *(dp--) = *(sp--); 02212 } 02213 } 02214 } 02215 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 02216 { 02217 if (row_info->bit_depth == 8) 02218 { 02219 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 02220 png_bytep dp = sp + (png_size_t)row_width * 2; 02221 for (i = 0; i < row_width; i++) 02222 { 02223 *(dp--) = *(sp--); 02224 *(dp--) = *sp; 02225 *(dp--) = *sp; 02226 *(dp--) = *(sp--); 02227 } 02228 } 02229 else 02230 { 02231 png_bytep sp = row + (png_size_t)row_width * 4 - 1; 02232 png_bytep dp = sp + (png_size_t)row_width * 4; 02233 for (i = 0; i < row_width; i++) 02234 { 02235 *(dp--) = *(sp--); 02236 *(dp--) = *(sp--); 02237 *(dp--) = *sp; 02238 *(dp--) = *(sp - 1); 02239 *(dp--) = *sp; 02240 *(dp--) = *(sp - 1); 02241 *(dp--) = *(sp--); 02242 *(dp--) = *(sp--); 02243 } 02244 } 02245 } 02246 row_info->channels += (png_byte)2; 02247 row_info->color_type |= PNG_COLOR_MASK_COLOR; 02248 row_info->pixel_depth = (png_byte)(row_info->channels * 02249 row_info->bit_depth); 02250 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 02251 } 02252 } 02253 #endif 02254 02255 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 02256 /* Reduce RGB files to grayscale, with or without alpha 02257 * using the equation given in Poynton's ColorFAQ at 02258 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008) 02259 * New link: 02260 * <http://www.poynton.com/notes/colour_and_gamma/> 02261 * Charles Poynton poynton at poynton.com 02262 * 02263 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 02264 * 02265 * We approximate this with 02266 * 02267 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B 02268 * 02269 * which can be expressed with integers as 02270 * 02271 * Y = (6969 * R + 23434 * G + 2365 * B)/32768 02272 * 02273 * The calculation is to be done in a linear colorspace. 02274 * 02275 * Other integer coefficents can be used via png_set_rgb_to_gray(). 02276 */ 02277 int /* PRIVATE */ 02278 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) 02279 02280 { 02281 png_uint_32 i; 02282 02283 png_uint_32 row_width = row_info->width; 02284 int rgb_error = 0; 02285 02286 png_debug(1, "in png_do_rgb_to_gray"); 02287 if ( 02288 #if defined(PNG_USELESS_TESTS_SUPPORTED) 02289 row != NULL && row_info != NULL && 02290 #endif 02291 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 02292 { 02293 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 02294 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 02295 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; 02296 02297 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 02298 { 02299 if (row_info->bit_depth == 8) 02300 { 02301 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 02302 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 02303 { 02304 png_bytep sp = row; 02305 png_bytep dp = row; 02306 02307 for (i = 0; i < row_width; i++) 02308 { 02309 png_byte red = png_ptr->gamma_to_1[*(sp++)]; 02310 png_byte green = png_ptr->gamma_to_1[*(sp++)]; 02311 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 02312 if (red != green || red != blue) 02313 { 02314 rgb_error |= 1; 02315 *(dp++) = png_ptr->gamma_from_1[ 02316 (rc*red + gc*green + bc*blue)>>15]; 02317 } 02318 else 02319 *(dp++) = *(sp - 1); 02320 } 02321 } 02322 else 02323 #endif 02324 { 02325 png_bytep sp = row; 02326 png_bytep dp = row; 02327 for (i = 0; i < row_width; i++) 02328 { 02329 png_byte red = *(sp++); 02330 png_byte green = *(sp++); 02331 png_byte blue = *(sp++); 02332 if (red != green || red != blue) 02333 { 02334 rgb_error |= 1; 02335 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 02336 } 02337 else 02338 *(dp++) = *(sp - 1); 02339 } 02340 } 02341 } 02342 02343 else /* RGB bit_depth == 16 */ 02344 { 02345 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 02346 if (png_ptr->gamma_16_to_1 != NULL && 02347 png_ptr->gamma_16_from_1 != NULL) 02348 { 02349 png_bytep sp = row; 02350 png_bytep dp = row; 02351 for (i = 0; i < row_width; i++) 02352 { 02353 png_uint_16 red, green, blue, w; 02354 02355 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02356 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02357 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02358 02359 if (red == green && red == blue) 02360 w = red; 02361 else 02362 { 02363 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 02364 png_ptr->gamma_shift][red>>8]; 02365 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> 02366 png_ptr->gamma_shift][green>>8]; 02367 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 02368 png_ptr->gamma_shift][blue>>8]; 02369 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 02370 + bc*blue_1)>>15); 02371 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 02372 png_ptr->gamma_shift][gray16 >> 8]; 02373 rgb_error |= 1; 02374 } 02375 02376 *(dp++) = (png_byte)((w>>8) & 0xff); 02377 *(dp++) = (png_byte)(w & 0xff); 02378 } 02379 } 02380 else 02381 #endif 02382 { 02383 png_bytep sp = row; 02384 png_bytep dp = row; 02385 for (i = 0; i < row_width; i++) 02386 { 02387 png_uint_16 red, green, blue, gray16; 02388 02389 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02390 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02391 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02392 02393 if (red != green || red != blue) 02394 rgb_error |= 1; 02395 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 02396 *(dp++) = (png_byte)((gray16>>8) & 0xff); 02397 *(dp++) = (png_byte)(gray16 & 0xff); 02398 } 02399 } 02400 } 02401 } 02402 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 02403 { 02404 if (row_info->bit_depth == 8) 02405 { 02406 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 02407 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 02408 { 02409 png_bytep sp = row; 02410 png_bytep dp = row; 02411 for (i = 0; i < row_width; i++) 02412 { 02413 png_byte red = png_ptr->gamma_to_1[*(sp++)]; 02414 png_byte green = png_ptr->gamma_to_1[*(sp++)]; 02415 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 02416 if (red != green || red != blue) 02417 rgb_error |= 1; 02418 *(dp++) = png_ptr->gamma_from_1 02419 [(rc*red + gc*green + bc*blue)>>15]; 02420 *(dp++) = *(sp++); /* alpha */ 02421 } 02422 } 02423 else 02424 #endif 02425 { 02426 png_bytep sp = row; 02427 png_bytep dp = row; 02428 for (i = 0; i < row_width; i++) 02429 { 02430 png_byte red = *(sp++); 02431 png_byte green = *(sp++); 02432 png_byte blue = *(sp++); 02433 if (red != green || red != blue) 02434 rgb_error |= 1; 02435 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 02436 *(dp++) = *(sp++); /* alpha */ 02437 } 02438 } 02439 } 02440 else /* RGBA bit_depth == 16 */ 02441 { 02442 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 02443 if (png_ptr->gamma_16_to_1 != NULL && 02444 png_ptr->gamma_16_from_1 != NULL) 02445 { 02446 png_bytep sp = row; 02447 png_bytep dp = row; 02448 for (i = 0; i < row_width; i++) 02449 { 02450 png_uint_16 red, green, blue, w; 02451 02452 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02453 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02454 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 02455 02456 if (red == green && red == blue) 02457 w = red; 02458 else 02459 { 02460 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 02461 png_ptr->gamma_shift][red>>8]; 02462 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> 02463 png_ptr->gamma_shift][green>>8]; 02464 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 02465 png_ptr->gamma_shift][blue>>8]; 02466 png_uint_16 gray16 = (png_uint_16)((rc * red_1 02467 + gc * green_1 + bc * blue_1)>>15); 02468 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 02469 png_ptr->gamma_shift][gray16 >> 8]; 02470 rgb_error |= 1; 02471 } 02472 02473 *(dp++) = (png_byte)((w>>8) & 0xff); 02474 *(dp++) = (png_byte)(w & 0xff); 02475 *(dp++) = *(sp++); /* alpha */ 02476 *(dp++) = *(sp++); 02477 } 02478 } 02479 else 02480 #endif 02481 { 02482 png_bytep sp = row; 02483 png_bytep dp = row; 02484 for (i = 0; i < row_width; i++) 02485 { 02486 png_uint_16 red, green, blue, gray16; 02487 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 02488 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 02489 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 02490 if (red != green || red != blue) 02491 rgb_error |= 1; 02492 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 02493 *(dp++) = (png_byte)((gray16>>8) & 0xff); 02494 *(dp++) = (png_byte)(gray16 & 0xff); 02495 *(dp++) = *(sp++); /* alpha */ 02496 *(dp++) = *(sp++); 02497 } 02498 } 02499 } 02500 } 02501 row_info->channels -= (png_byte)2; 02502 row_info->color_type &= ~PNG_COLOR_MASK_COLOR; 02503 row_info->pixel_depth = (png_byte)(row_info->channels * 02504 row_info->bit_depth); 02505 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 02506 } 02507 return rgb_error; 02508 } 02509 #endif 02510 02511 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth 02512 * large of png_color. This lets grayscale images be treated as 02513 * paletted. Most useful for gamma correction and simplification 02514 * of code. 02515 */ 02516 void PNGAPI 02517 png_build_grayscale_palette(int bit_depth, png_colorp palette) 02518 { 02519 int num_palette; 02520 int color_inc; 02521 int i; 02522 int v; 02523 02524 png_debug(1, "in png_do_build_grayscale_palette"); 02525 if (palette == NULL) 02526 return; 02527 02528 switch (bit_depth) 02529 { 02530 case 1: 02531 num_palette = 2; 02532 color_inc = 0xff; 02533 break; 02534 02535 case 2: 02536 num_palette = 4; 02537 color_inc = 0x55; 02538 break; 02539 02540 case 4: 02541 num_palette = 16; 02542 color_inc = 0x11; 02543 break; 02544 02545 case 8: 02546 num_palette = 256; 02547 color_inc = 1; 02548 break; 02549 02550 default: 02551 num_palette = 0; 02552 color_inc = 0; 02553 break; 02554 } 02555 02556 for (i = 0, v = 0; i < num_palette; i++, v += color_inc) 02557 { 02558 palette[i].red = (png_byte)v; 02559 palette[i].green = (png_byte)v; 02560 palette[i].blue = (png_byte)v; 02561 } 02562 } 02563 02564 /* This function is currently unused. Do we really need it? */ 02565 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) 02566 void /* PRIVATE */ 02567 png_correct_palette(png_structp png_ptr, png_colorp palette, 02568 int num_palette) 02569 { 02570 png_debug(1, "in png_correct_palette"); 02571 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 02572 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 02573 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) 02574 { 02575 png_color back, back_1; 02576 02577 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 02578 { 02579 back.red = png_ptr->gamma_table[png_ptr->background.red]; 02580 back.green = png_ptr->gamma_table[png_ptr->background.green]; 02581 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 02582 02583 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 02584 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 02585 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 02586 } 02587 else 02588 { 02589 double g; 02590 02591 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); 02592 02593 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || 02594 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) 02595 { 02596 back.red = png_ptr->background.red; 02597 back.green = png_ptr->background.green; 02598 back.blue = png_ptr->background.blue; 02599 } 02600 else 02601 { 02602 back.red = 02603 (png_byte)(pow((double)png_ptr->background.red/255, g) * 02604 255.0 + 0.5); 02605 back.green = 02606 (png_byte)(pow((double)png_ptr->background.green/255, g) * 02607 255.0 + 0.5); 02608 back.blue = 02609 (png_byte)(pow((double)png_ptr->background.blue/255, g) * 02610 255.0 + 0.5); 02611 } 02612 02613 g = 1.0 / png_ptr->background_gamma; 02614 02615 back_1.red = 02616 (png_byte)(pow((double)png_ptr->background.red/255, g) * 02617 255.0 + 0.5); 02618 back_1.green = 02619 (png_byte)(pow((double)png_ptr->background.green/255, g) * 02620 255.0 + 0.5); 02621 back_1.blue = 02622 (png_byte)(pow((double)png_ptr->background.blue/255, g) * 02623 255.0 + 0.5); 02624 } 02625 02626 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 02627 { 02628 png_uint_32 i; 02629 02630 for (i = 0; i < (png_uint_32)num_palette; i++) 02631 { 02632 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) 02633 { 02634 palette[i] = back; 02635 } 02636 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) 02637 { 02638 png_byte v, w; 02639 02640 v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; 02641 png_composite(w, v, png_ptr->trans[i], back_1.red); 02642 palette[i].red = png_ptr->gamma_from_1[w]; 02643 02644 v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; 02645 png_composite(w, v, png_ptr->trans[i], back_1.green); 02646 palette[i].green = png_ptr->gamma_from_1[w]; 02647 02648 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; 02649 png_composite(w, v, png_ptr->trans[i], back_1.blue); 02650 palette[i].blue = png_ptr->gamma_from_1[w]; 02651 } 02652 else 02653 { 02654 palette[i].red = png_ptr->gamma_table[palette[i].red]; 02655 palette[i].green = png_ptr->gamma_table[palette[i].green]; 02656 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 02657 } 02658 } 02659 } 02660 else 02661 { 02662 int i; 02663 02664 for (i = 0; i < num_palette; i++) 02665 { 02666 if (palette[i].red == (png_byte)png_ptr->trans_values.gray) 02667 { 02668 palette[i] = back; 02669 } 02670 else 02671 { 02672 palette[i].red = png_ptr->gamma_table[palette[i].red]; 02673 palette[i].green = png_ptr->gamma_table[palette[i].green]; 02674 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 02675 } 02676 } 02677 } 02678 } 02679 else 02680 #endif 02681 #if defined(PNG_READ_GAMMA_SUPPORTED) 02682 if (png_ptr->transformations & PNG_GAMMA) 02683 { 02684 int i; 02685 02686 for (i = 0; i < num_palette; i++) 02687 { 02688 palette[i].red = png_ptr->gamma_table[palette[i].red]; 02689 palette[i].green = png_ptr->gamma_table[palette[i].green]; 02690 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 02691 } 02692 } 02693 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 02694 else 02695 #endif 02696 #endif 02697 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 02698 if (png_ptr->transformations & PNG_BACKGROUND) 02699 { 02700 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 02701 { 02702 png_color back; 02703 02704 back.red = (png_byte)png_ptr->background.red; 02705 back.green = (png_byte)png_ptr->background.green; 02706 back.blue = (png_byte)png_ptr->background.blue; 02707 02708 for (i = 0; i < (int)png_ptr->num_trans; i++) 02709 { 02710 if (png_ptr->trans[i] == 0) 02711 { 02712 palette[i].red = back.red; 02713 palette[i].green = back.green; 02714 palette[i].blue = back.blue; 02715 } 02716 else if (png_ptr->trans[i] != 0xff) 02717 { 02718 png_composite(palette[i].red, png_ptr->palette[i].red, 02719 png_ptr->trans[i], back.red); 02720 png_composite(palette[i].green, png_ptr->palette[i].green, 02721 png_ptr->trans[i], back.green); 02722 png_composite(palette[i].blue, png_ptr->palette[i].blue, 02723 png_ptr->trans[i], back.blue); 02724 } 02725 } 02726 } 02727 else /* Assume grayscale palette (what else could it be?) */ 02728 { 02729 int i; 02730 02731 for (i = 0; i < num_palette; i++) 02732 { 02733 if (i == (png_byte)png_ptr->trans_values.gray) 02734 { 02735 palette[i].red = (png_byte)png_ptr->background.red; 02736 palette[i].green = (png_byte)png_ptr->background.green; 02737 palette[i].blue = (png_byte)png_ptr->background.blue; 02738 } 02739 } 02740 } 02741 } 02742 #endif 02743 } 02744 #endif 02745 02746 #if defined(PNG_READ_BACKGROUND_SUPPORTED) 02747 /* Replace any alpha or transparency with the supplied background color. 02748 * "background" is already in the screen gamma, while "background_1" is 02749 * at a gamma of 1.0. Paletted files have already been taken care of. 02750 */ 02751 void /* PRIVATE */ 02752 png_do_background(png_row_infop row_info, png_bytep row, 02753 png_color_16p trans_values, png_color_16p background 02754 #if defined(PNG_READ_GAMMA_SUPPORTED) 02755 , png_color_16p background_1, 02756 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, 02757 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, 02758 png_uint_16pp gamma_16_to_1, int gamma_shift 02759 #endif 02760 ) 02761 { 02762 png_bytep sp, dp; 02763 png_uint_32 i; 02764 png_uint_32 row_width=row_info->width; 02765 int shift; 02766 02767 png_debug(1, "in png_do_background"); 02768 if (background != NULL && 02769 #if defined(PNG_USELESS_TESTS_SUPPORTED) 02770 row != NULL && row_info != NULL && 02771 #endif 02772 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || 02773 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) 02774 { 02775 switch (row_info->color_type) 02776 { 02777 case PNG_COLOR_TYPE_GRAY: 02778 { 02779 switch (row_info->bit_depth) 02780 { 02781 case 1: 02782 { 02783 sp = row; 02784 shift = 7; 02785 for (i = 0; i < row_width; i++) 02786 { 02787 if ((png_uint_16)((*sp >> shift) & 0x01) 02788 == trans_values->gray) 02789 { 02790 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); 02791 *sp |= (png_byte)(background->gray << shift); 02792 } 02793 if (!shift) 02794 { 02795 shift = 7; 02796 sp++; 02797 } 02798 else 02799 shift--; 02800 } 02801 break; 02802 } 02803 02804 case 2: 02805 { 02806 #if defined(PNG_READ_GAMMA_SUPPORTED) 02807 if (gamma_table != NULL) 02808 { 02809 sp = row; 02810 shift = 6; 02811 for (i = 0; i < row_width; i++) 02812 { 02813 if ((png_uint_16)((*sp >> shift) & 0x03) 02814 == trans_values->gray) 02815 { 02816 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 02817 *sp |= (png_byte)(background->gray << shift); 02818 } 02819 else 02820 { 02821 png_byte p = (png_byte)((*sp >> shift) & 0x03); 02822 png_byte g = (png_byte)((gamma_table [p | (p << 2) | 02823 (p << 4) | (p << 6)] >> 6) & 0x03); 02824 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 02825 *sp |= (png_byte)(g << shift); 02826 } 02827 if (!shift) 02828 { 02829 shift = 6; 02830 sp++; 02831 } 02832 else 02833 shift -= 2; 02834 } 02835 } 02836 else 02837 #endif 02838 { 02839 sp = row; 02840 shift = 6; 02841 for (i = 0; i < row_width; i++) 02842 { 02843 if ((png_uint_16)((*sp >> shift) & 0x03) 02844 == trans_values->gray) 02845 { 02846 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 02847 *sp |= (png_byte)(background->gray << shift); 02848 } 02849 if (!shift) 02850 { 02851 shift = 6; 02852 sp++; 02853 } 02854 else 02855 shift -= 2; 02856 } 02857 } 02858 break; 02859 } 02860 02861 case 4: 02862 { 02863 #if defined(PNG_READ_GAMMA_SUPPORTED) 02864 if (gamma_table != NULL) 02865 { 02866 sp = row; 02867 shift = 4; 02868 for (i = 0; i < row_width; i++) 02869 { 02870 if ((png_uint_16)((*sp >> shift) & 0x0f) 02871 == trans_values->gray) 02872 { 02873 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 02874 *sp |= (png_byte)(background->gray << shift); 02875 } 02876 else 02877 { 02878 png_byte p = (png_byte)((*sp >> shift) & 0x0f); 02879 png_byte g = (png_byte)((gamma_table[p | 02880 (p << 4)] >> 4) & 0x0f); 02881 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 02882 *sp |= (png_byte)(g << shift); 02883 } 02884 if (!shift) 02885 { 02886 shift = 4; 02887 sp++; 02888 } 02889 else 02890 shift -= 4; 02891 } 02892 } 02893 else 02894 #endif 02895 { 02896 sp = row; 02897 shift = 4; 02898 for (i = 0; i < row_width; i++) 02899 { 02900 if ((png_uint_16)((*sp >> shift) & 0x0f) 02901 == trans_values->gray) 02902 { 02903 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 02904 *sp |= (png_byte)(background->gray << shift); 02905 } 02906 if (!shift) 02907 { 02908 shift = 4; 02909 sp++; 02910 } 02911 else 02912 shift -= 4; 02913 } 02914 } 02915 break; 02916 } 02917 02918 case 8: 02919 { 02920 #if defined(PNG_READ_GAMMA_SUPPORTED) 02921 if (gamma_table != NULL) 02922 { 02923 sp = row; 02924 for (i = 0; i < row_width; i++, sp++) 02925 { 02926 if (*sp == trans_values->gray) 02927 { 02928 *sp = (png_byte)background->gray; 02929 } 02930 else 02931 { 02932 *sp = gamma_table[*sp]; 02933 } 02934 } 02935 } 02936 else 02937 #endif 02938 { 02939 sp = row; 02940 for (i = 0; i < row_width; i++, sp++) 02941 { 02942 if (*sp == trans_values->gray) 02943 { 02944 *sp = (png_byte)background->gray; 02945 } 02946 } 02947 } 02948 break; 02949 } 02950 02951 case 16: 02952 { 02953 #if defined(PNG_READ_GAMMA_SUPPORTED) 02954 if (gamma_16 != NULL) 02955 { 02956 sp = row; 02957 for (i = 0; i < row_width; i++, sp += 2) 02958 { 02959 png_uint_16 v; 02960 02961 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 02962 if (v == trans_values->gray) 02963 { 02964 /* Background is already in screen gamma */ 02965 *sp = (png_byte)((background->gray >> 8) & 0xff); 02966 *(sp + 1) = (png_byte)(background->gray & 0xff); 02967 } 02968 else 02969 { 02970 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 02971 *sp = (png_byte)((v >> 8) & 0xff); 02972 *(sp + 1) = (png_byte)(v & 0xff); 02973 } 02974 } 02975 } 02976 else 02977 #endif 02978 { 02979 sp = row; 02980 for (i = 0; i < row_width; i++, sp += 2) 02981 { 02982 png_uint_16 v; 02983 02984 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 02985 if (v == trans_values->gray) 02986 { 02987 *sp = (png_byte)((background->gray >> 8) & 0xff); 02988 *(sp + 1) = (png_byte)(background->gray & 0xff); 02989 } 02990 } 02991 } 02992 break; 02993 } 02994 } 02995 break; 02996 } 02997 02998 case PNG_COLOR_TYPE_RGB: 02999 { 03000 if (row_info->bit_depth == 8) 03001 { 03002 #if defined(PNG_READ_GAMMA_SUPPORTED) 03003 if (gamma_table != NULL) 03004 { 03005 sp = row; 03006 for (i = 0; i < row_width; i++, sp += 3) 03007 { 03008 if (*sp == trans_values->red && 03009 *(sp + 1) == trans_values->green && 03010 *(sp + 2) == trans_values->blue) 03011 { 03012 *sp = (png_byte)background->red; 03013 *(sp + 1) = (png_byte)background->green; 03014 *(sp + 2) = (png_byte)background->blue; 03015 } 03016 else 03017 { 03018 *sp = gamma_table[*sp]; 03019 *(sp + 1) = gamma_table[*(sp + 1)]; 03020 *(sp + 2) = gamma_table[*(sp + 2)]; 03021 } 03022 } 03023 } 03024 else 03025 #endif 03026 { 03027 sp = row; 03028 for (i = 0; i < row_width; i++, sp += 3) 03029 { 03030 if (*sp == trans_values->red && 03031 *(sp + 1) == trans_values->green && 03032 *(sp + 2) == trans_values->blue) 03033 { 03034 *sp = (png_byte)background->red; 03035 *(sp + 1) = (png_byte)background->green; 03036 *(sp + 2) = (png_byte)background->blue; 03037 } 03038 } 03039 } 03040 } 03041 else /* if (row_info->bit_depth == 16) */ 03042 { 03043 #if defined(PNG_READ_GAMMA_SUPPORTED) 03044 if (gamma_16 != NULL) 03045 { 03046 sp = row; 03047 for (i = 0; i < row_width; i++, sp += 6) 03048 { 03049 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03050 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 03051 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 03052 if (r == trans_values->red && g == trans_values->green && 03053 b == trans_values->blue) 03054 { 03055 /* Background is already in screen gamma */ 03056 *sp = (png_byte)((background->red >> 8) & 0xff); 03057 *(sp + 1) = (png_byte)(background->red & 0xff); 03058 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 03059 *(sp + 3) = (png_byte)(background->green & 0xff); 03060 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 03061 *(sp + 5) = (png_byte)(background->blue & 0xff); 03062 } 03063 else 03064 { 03065 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03066 *sp = (png_byte)((v >> 8) & 0xff); 03067 *(sp + 1) = (png_byte)(v & 0xff); 03068 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 03069 *(sp + 2) = (png_byte)((v >> 8) & 0xff); 03070 *(sp + 3) = (png_byte)(v & 0xff); 03071 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 03072 *(sp + 4) = (png_byte)((v >> 8) & 0xff); 03073 *(sp + 5) = (png_byte)(v & 0xff); 03074 } 03075 } 03076 } 03077 else 03078 #endif 03079 { 03080 sp = row; 03081 for (i = 0; i < row_width; i++, sp += 6) 03082 { 03083 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); 03084 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 03085 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 03086 03087 if (r == trans_values->red && g == trans_values->green && 03088 b == trans_values->blue) 03089 { 03090 *sp = (png_byte)((background->red >> 8) & 0xff); 03091 *(sp + 1) = (png_byte)(background->red & 0xff); 03092 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 03093 *(sp + 3) = (png_byte)(background->green & 0xff); 03094 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 03095 *(sp + 5) = (png_byte)(background->blue & 0xff); 03096 } 03097 } 03098 } 03099 } 03100 break; 03101 } 03102 03103 case PNG_COLOR_TYPE_GRAY_ALPHA: 03104 { 03105 if (row_info->bit_depth == 8) 03106 { 03107 #if defined(PNG_READ_GAMMA_SUPPORTED) 03108 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 03109 gamma_table != NULL) 03110 { 03111 sp = row; 03112 dp = row; 03113 for (i = 0; i < row_width; i++, sp += 2, dp++) 03114 { 03115 png_uint_16 a = *(sp + 1); 03116 03117 if (a == 0xff) 03118 { 03119 *dp = gamma_table[*sp]; 03120 } 03121 else if (a == 0) 03122 { 03123 /* Background is already in screen gamma */ 03124 *dp = (png_byte)background->gray; 03125 } 03126 else 03127 { 03128 png_byte v, w; 03129 03130 v = gamma_to_1[*sp]; 03131 png_composite(w, v, a, background_1->gray); 03132 *dp = gamma_from_1[w]; 03133 } 03134 } 03135 } 03136 else 03137 #endif 03138 { 03139 sp = row; 03140 dp = row; 03141 for (i = 0; i < row_width; i++, sp += 2, dp++) 03142 { 03143 png_byte a = *(sp + 1); 03144 03145 if (a == 0xff) 03146 { 03147 *dp = *sp; 03148 } 03149 #if defined(PNG_READ_GAMMA_SUPPORTED) 03150 else if (a == 0) 03151 { 03152 *dp = (png_byte)background->gray; 03153 } 03154 else 03155 { 03156 png_composite(*dp, *sp, a, background_1->gray); 03157 } 03158 #else 03159 *dp = (png_byte)background->gray; 03160 #endif 03161 } 03162 } 03163 } 03164 else /* if (png_ptr->bit_depth == 16) */ 03165 { 03166 #if defined(PNG_READ_GAMMA_SUPPORTED) 03167 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 03168 gamma_16_to_1 != NULL) 03169 { 03170 sp = row; 03171 dp = row; 03172 for (i = 0; i < row_width; i++, sp += 4, dp += 2) 03173 { 03174 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 03175 03176 if (a == (png_uint_16)0xffff) 03177 { 03178 png_uint_16 v; 03179 03180 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03181 *dp = (png_byte)((v >> 8) & 0xff); 03182 *(dp + 1) = (png_byte)(v & 0xff); 03183 } 03184 #if defined(PNG_READ_GAMMA_SUPPORTED) 03185 else if (a == 0) 03186 #else 03187 else 03188 #endif 03189 { 03190 /* Background is already in screen gamma */ 03191 *dp = (png_byte)((background->gray >> 8) & 0xff); 03192 *(dp + 1) = (png_byte)(background->gray & 0xff); 03193 } 03194 #if defined(PNG_READ_GAMMA_SUPPORTED) 03195 else 03196 { 03197 png_uint_16 g, v, w; 03198 03199 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 03200 png_composite_16(v, g, a, background_1->gray); 03201 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; 03202 *dp = (png_byte)((w >> 8) & 0xff); 03203 *(dp + 1) = (png_byte)(w & 0xff); 03204 } 03205 #endif 03206 } 03207 } 03208 else 03209 #endif 03210 { 03211 sp = row; 03212 dp = row; 03213 for (i = 0; i < row_width; i++, sp += 4, dp += 2) 03214 { 03215 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 03216 if (a == (png_uint_16)0xffff) 03217 { 03218 png_memcpy(dp, sp, 2); 03219 } 03220 #if defined(PNG_READ_GAMMA_SUPPORTED) 03221 else if (a == 0) 03222 #else 03223 else 03224 #endif 03225 { 03226 *dp = (png_byte)((background->gray >> 8) & 0xff); 03227 *(dp + 1) = (png_byte)(background->gray & 0xff); 03228 } 03229 #if defined(PNG_READ_GAMMA_SUPPORTED) 03230 else 03231 { 03232 png_uint_16 g, v; 03233 03234 g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03235 png_composite_16(v, g, a, background_1->gray); 03236 *dp = (png_byte)((v >> 8) & 0xff); 03237 *(dp + 1) = (png_byte)(v & 0xff); 03238 } 03239 #endif 03240 } 03241 } 03242 } 03243 break; 03244 } 03245 03246 case PNG_COLOR_TYPE_RGB_ALPHA: 03247 { 03248 if (row_info->bit_depth == 8) 03249 { 03250 #if defined(PNG_READ_GAMMA_SUPPORTED) 03251 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 03252 gamma_table != NULL) 03253 { 03254 sp = row; 03255 dp = row; 03256 for (i = 0; i < row_width; i++, sp += 4, dp += 3) 03257 { 03258 png_byte a = *(sp + 3); 03259 03260 if (a == 0xff) 03261 { 03262 *dp = gamma_table[*sp]; 03263 *(dp + 1) = gamma_table[*(sp + 1)]; 03264 *(dp + 2) = gamma_table[*(sp + 2)]; 03265 } 03266 else if (a == 0) 03267 { 03268 /* Background is already in screen gamma */ 03269 *dp = (png_byte)background->red; 03270 *(dp + 1) = (png_byte)background->green; 03271 *(dp + 2) = (png_byte)background->blue; 03272 } 03273 else 03274 { 03275 png_byte v, w; 03276 03277 v = gamma_to_1[*sp]; 03278 png_composite(w, v, a, background_1->red); 03279 *dp = gamma_from_1[w]; 03280 v = gamma_to_1[*(sp + 1)]; 03281 png_composite(w, v, a, background_1->green); 03282 *(dp + 1) = gamma_from_1[w]; 03283 v = gamma_to_1[*(sp + 2)]; 03284 png_composite(w, v, a, background_1->blue); 03285 *(dp + 2) = gamma_from_1[w]; 03286 } 03287 } 03288 } 03289 else 03290 #endif 03291 { 03292 sp = row; 03293 dp = row; 03294 for (i = 0; i < row_width; i++, sp += 4, dp += 3) 03295 { 03296 png_byte a = *(sp + 3); 03297 03298 if (a == 0xff) 03299 { 03300 *dp = *sp; 03301 *(dp + 1) = *(sp + 1); 03302 *(dp + 2) = *(sp + 2); 03303 } 03304 else if (a == 0) 03305 { 03306 *dp = (png_byte)background->red; 03307 *(dp + 1) = (png_byte)background->green; 03308 *(dp + 2) = (png_byte)background->blue; 03309 } 03310 else 03311 { 03312 png_composite(*dp, *sp, a, background->red); 03313 png_composite(*(dp + 1), *(sp + 1), a, 03314 background->green); 03315 png_composite(*(dp + 2), *(sp + 2), a, 03316 background->blue); 03317 } 03318 } 03319 } 03320 } 03321 else /* if (row_info->bit_depth == 16) */ 03322 { 03323 #if defined(PNG_READ_GAMMA_SUPPORTED) 03324 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 03325 gamma_16_to_1 != NULL) 03326 { 03327 sp = row; 03328 dp = row; 03329 for (i = 0; i < row_width; i++, sp += 8, dp += 6) 03330 { 03331 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 03332 << 8) + (png_uint_16)(*(sp + 7))); 03333 if (a == (png_uint_16)0xffff) 03334 { 03335 png_uint_16 v; 03336 03337 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 03338 *dp = (png_byte)((v >> 8) & 0xff); 03339 *(dp + 1) = (png_byte)(v & 0xff); 03340 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 03341 *(dp + 2) = (png_byte)((v >> 8) & 0xff); 03342 *(dp + 3) = (png_byte)(v & 0xff); 03343 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 03344 *(dp + 4) = (png_byte)((v >> 8) & 0xff); 03345 *(dp + 5) = (png_byte)(v & 0xff); 03346 } 03347 else if (a == 0) 03348 { 03349 /* Background is already in screen gamma */ 03350 *dp = (png_byte)((background->red >> 8) & 0xff); 03351 *(dp + 1) = (png_byte)(background->red & 0xff); 03352 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 03353 *(dp + 3) = (png_byte)(background->green & 0xff); 03354 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 03355 *(dp + 5) = (png_byte)(background->blue & 0xff); 03356 } 03357 else 03358 { 03359 png_uint_16 v, w, x; 03360 03361 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 03362 png_composite_16(w, v, a, background_1->red); 03363 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 03364 *dp = (png_byte)((x >> 8) & 0xff); 03365 *(dp + 1) = (png_byte)(x & 0xff); 03366 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 03367 png_composite_16(w, v, a, background_1->green); 03368 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 03369 *(dp + 2) = (png_byte)((x >> 8) & 0xff); 03370 *(dp + 3) = (png_byte)(x & 0xff); 03371 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 03372 png_composite_16(w, v, a, background_1->blue); 03373 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; 03374 *(dp + 4) = (png_byte)((x >> 8) & 0xff); 03375 *(dp + 5) = (png_byte)(x & 0xff); 03376 } 03377 } 03378 } 03379 else 03380 #endif 03381 { 03382 sp = row; 03383 dp = row; 03384 for (i = 0; i < row_width; i++, sp += 8, dp += 6) 03385 { 03386 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 03387 << 8) + (png_uint_16)(*(sp + 7))); 03388 if (a == (png_uint_16)0xffff) 03389 { 03390 png_memcpy(dp, sp, 6); 03391 } 03392 else if (a == 0) 03393 { 03394 *dp = (png_byte)((background->red >> 8) & 0xff); 03395 *(dp + 1) = (png_byte)(background->red & 0xff); 03396 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 03397 *(dp + 3) = (png_byte)(background->green & 0xff); 03398 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 03399 *(dp + 5) = (png_byte)(background->blue & 0xff); 03400 } 03401 else 03402 { 03403 png_uint_16 v; 03404 03405 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 03406 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 03407 + *(sp + 3)); 03408 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 03409 + *(sp + 5)); 03410 03411 png_composite_16(v, r, a, background->red); 03412 *dp = (png_byte)((v >> 8) & 0xff); 03413 *(dp + 1) = (png_byte)(v & 0xff); 03414 png_composite_16(v, g, a, background->green); 03415 *(dp + 2) = (png_byte)((v >> 8) & 0xff); 03416 *(dp + 3) = (png_byte)(v & 0xff); 03417 png_composite_16(v, b, a, background->blue); 03418 *(dp + 4) = (png_byte)((v >> 8) & 0xff); 03419 *(dp + 5) = (png_byte)(v & 0xff); 03420 } 03421 } 03422 } 03423 } 03424 break; 03425 } 03426 } 03427 03428 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 03429 { 03430 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; 03431 row_info->channels--; 03432 row_info->pixel_depth = (png_byte)(row_info->channels * 03433 row_info->bit_depth); 03434 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 03435 } 03436 } 03437 } 03438 #endif 03439 03440 #if defined(PNG_READ_GAMMA_SUPPORTED) 03441 /* Gamma correct the image, avoiding the alpha channel. Make sure 03442 * you do this after you deal with the transparency issue on grayscale 03443 * or RGB images. If your bit depth is 8, use gamma_table, if it 03444 * is 16, use gamma_16_table and gamma_shift. Build these with 03445 * build_gamma_table(). 03446 */ 03447 void /* PRIVATE */ 03448 png_do_gamma(png_row_infop row_info, png_bytep row, 03449 png_bytep gamma_table, png_uint_16pp gamma_16_table, 03450 int gamma_shift) 03451 { 03452 png_bytep sp; 03453 png_uint_32 i; 03454 png_uint_32 row_width=row_info->width; 03455 03456 png_debug(1, "in png_do_gamma"); 03457 if ( 03458 #if defined(PNG_USELESS_TESTS_SUPPORTED) 03459 row != NULL && row_info != NULL && 03460 #endif 03461 ((row_info->bit_depth <= 8 && gamma_table != NULL) || 03462 (row_info->bit_depth == 16 && gamma_16_table != NULL))) 03463 { 03464 switch (row_info->color_type) 03465 { 03466 case PNG_COLOR_TYPE_RGB: 03467 { 03468 if (row_info->bit_depth == 8) 03469 { 03470 sp = row; 03471 for (i = 0; i < row_width; i++) 03472 { 03473 *sp = gamma_table[*sp]; 03474 sp++; 03475 *sp = gamma_table[*sp]; 03476 sp++; 03477 *sp = gamma_table[*sp]; 03478 sp++; 03479 } 03480 } 03481 else /* if (row_info->bit_depth == 16) */ 03482 { 03483 sp = row; 03484 for (i = 0; i < row_width; i++) 03485 { 03486 png_uint_16 v; 03487 03488 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03489 *sp = (png_byte)((v >> 8) & 0xff); 03490 *(sp + 1) = (png_byte)(v & 0xff); 03491 sp += 2; 03492 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03493 *sp = (png_byte)((v >> 8) & 0xff); 03494 *(sp + 1) = (png_byte)(v & 0xff); 03495 sp += 2; 03496 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03497 *sp = (png_byte)((v >> 8) & 0xff); 03498 *(sp + 1) = (png_byte)(v & 0xff); 03499 sp += 2; 03500 } 03501 } 03502 break; 03503 } 03504 03505 case PNG_COLOR_TYPE_RGB_ALPHA: 03506 { 03507 if (row_info->bit_depth == 8) 03508 { 03509 sp = row; 03510 for (i = 0; i < row_width; i++) 03511 { 03512 *sp = gamma_table[*sp]; 03513 sp++; 03514 *sp = gamma_table[*sp]; 03515 sp++; 03516 *sp = gamma_table[*sp]; 03517 sp++; 03518 sp++; 03519 } 03520 } 03521 else /* if (row_info->bit_depth == 16) */ 03522 { 03523 sp = row; 03524 for (i = 0; i < row_width; i++) 03525 { 03526 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03527 *sp = (png_byte)((v >> 8) & 0xff); 03528 *(sp + 1) = (png_byte)(v & 0xff); 03529 sp += 2; 03530 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03531 *sp = (png_byte)((v >> 8) & 0xff); 03532 *(sp + 1) = (png_byte)(v & 0xff); 03533 sp += 2; 03534 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03535 *sp = (png_byte)((v >> 8) & 0xff); 03536 *(sp + 1) = (png_byte)(v & 0xff); 03537 sp += 4; 03538 } 03539 } 03540 break; 03541 } 03542 03543 case PNG_COLOR_TYPE_GRAY_ALPHA: 03544 { 03545 if (row_info->bit_depth == 8) 03546 { 03547 sp = row; 03548 for (i = 0; i < row_width; i++) 03549 { 03550 *sp = gamma_table[*sp]; 03551 sp += 2; 03552 } 03553 } 03554 else /* if (row_info->bit_depth == 16) */ 03555 { 03556 sp = row; 03557 for (i = 0; i < row_width; i++) 03558 { 03559 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03560 *sp = (png_byte)((v >> 8) & 0xff); 03561 *(sp + 1) = (png_byte)(v & 0xff); 03562 sp += 4; 03563 } 03564 } 03565 break; 03566 } 03567 03568 case PNG_COLOR_TYPE_GRAY: 03569 { 03570 if (row_info->bit_depth == 2) 03571 { 03572 sp = row; 03573 for (i = 0; i < row_width; i += 4) 03574 { 03575 int a = *sp & 0xc0; 03576 int b = *sp & 0x30; 03577 int c = *sp & 0x0c; 03578 int d = *sp & 0x03; 03579 03580 *sp = (png_byte)( 03581 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 03582 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 03583 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 03584 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 03585 sp++; 03586 } 03587 } 03588 03589 if (row_info->bit_depth == 4) 03590 { 03591 sp = row; 03592 for (i = 0; i < row_width; i += 2) 03593 { 03594 int msb = *sp & 0xf0; 03595 int lsb = *sp & 0x0f; 03596 03597 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 03598 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 03599 sp++; 03600 } 03601 } 03602 03603 else if (row_info->bit_depth == 8) 03604 { 03605 sp = row; 03606 for (i = 0; i < row_width; i++) 03607 { 03608 *sp = gamma_table[*sp]; 03609 sp++; 03610 } 03611 } 03612 03613 else if (row_info->bit_depth == 16) 03614 { 03615 sp = row; 03616 for (i = 0; i < row_width; i++) 03617 { 03618 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 03619 *sp = (png_byte)((v >> 8) & 0xff); 03620 *(sp + 1) = (png_byte)(v & 0xff); 03621 sp += 2; 03622 } 03623 } 03624 break; 03625 } 03626 } 03627 } 03628 } 03629 #endif 03630 03631 #if defined(PNG_READ_EXPAND_SUPPORTED) 03632 /* Expands a palette row to an RGB or RGBA row depending 03633 * upon whether you supply trans and num_trans. 03634 */ 03635 void /* PRIVATE */ 03636 png_do_expand_palette(png_row_infop row_info, png_bytep row, 03637 png_colorp palette, png_bytep trans, int num_trans) 03638 { 03639 int shift, value; 03640 png_bytep sp, dp; 03641 png_uint_32 i; 03642 png_uint_32 row_width=row_info->width; 03643 03644 png_debug(1, "in png_do_expand_palette"); 03645 if ( 03646 #if defined(PNG_USELESS_TESTS_SUPPORTED) 03647 row != NULL && row_info != NULL && 03648 #endif 03649 row_info->color_type == PNG_COLOR_TYPE_PALETTE) 03650 { 03651 if (row_info->bit_depth < 8) 03652 { 03653 switch (row_info->bit_depth) 03654 { 03655 case 1: 03656 { 03657 sp = row + (png_size_t)((row_width - 1) >> 3); 03658 dp = row + (png_size_t)row_width - 1; 03659 shift = 7 - (int)((row_width + 7) & 0x07); 03660 for (i = 0; i < row_width; i++) 03661 { 03662 if ((*sp >> shift) & 0x01) 03663 *dp = 1; 03664 else 03665 *dp = 0; 03666 if (shift == 7) 03667 { 03668 shift = 0; 03669 sp--; 03670 } 03671 else 03672 shift++; 03673 03674 dp--; 03675 } 03676 break; 03677 } 03678 03679 case 2: 03680 { 03681 sp = row + (png_size_t)((row_width - 1) >> 2); 03682 dp = row + (png_size_t)row_width - 1; 03683 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 03684 for (i = 0; i < row_width; i++) 03685 { 03686 value = (*sp >> shift) & 0x03; 03687 *dp = (png_byte)value; 03688 if (shift == 6) 03689 { 03690 shift = 0; 03691 sp--; 03692 } 03693 else 03694 shift += 2; 03695 03696 dp--; 03697 } 03698 break; 03699 } 03700 03701 case 4: 03702 { 03703 sp = row + (png_size_t)((row_width - 1) >> 1); 03704 dp = row + (png_size_t)row_width - 1; 03705 shift = (int)((row_width & 0x01) << 2); 03706 for (i = 0; i < row_width; i++) 03707 { 03708 value = (*sp >> shift) & 0x0f; 03709 *dp = (png_byte)value; 03710 if (shift == 4) 03711 { 03712 shift = 0; 03713 sp--; 03714 } 03715 else 03716 shift += 4; 03717 03718 dp--; 03719 } 03720 break; 03721 } 03722 } 03723 row_info->bit_depth = 8; 03724 row_info->pixel_depth = 8; 03725 row_info->rowbytes = row_width; 03726 } 03727 switch (row_info->bit_depth) 03728 { 03729 case 8: 03730 { 03731 if (trans != NULL) 03732 { 03733 sp = row + (png_size_t)row_width - 1; 03734 dp = row + (png_size_t)(row_width << 2) - 1; 03735 03736 for (i = 0; i < row_width; i++) 03737 { 03738 if ((int)(*sp) >= num_trans) 03739 *dp-- = 0xff; 03740 else 03741 *dp-- = trans[*sp]; 03742 *dp-- = palette[*sp].blue; 03743 *dp-- = palette[*sp].green; 03744 *dp-- = palette[*sp].red; 03745 sp--; 03746 } 03747 row_info->bit_depth = 8; 03748 row_info->pixel_depth = 32; 03749 row_info->rowbytes = row_width * 4; 03750 row_info->color_type = 6; 03751 row_info->channels = 4; 03752 } 03753 else 03754 { 03755 sp = row + (png_size_t)row_width - 1; 03756 dp = row + (png_size_t)(row_width * 3) - 1; 03757 03758 for (i = 0; i < row_width; i++) 03759 { 03760 *dp-- = palette[*sp].blue; 03761 *dp-- = palette[*sp].green; 03762 *dp-- = palette[*sp].red; 03763 sp--; 03764 } 03765 03766 row_info->bit_depth = 8; 03767 row_info->pixel_depth = 24; 03768 row_info->rowbytes = row_width * 3; 03769 row_info->color_type = 2; 03770 row_info->channels = 3; 03771 } 03772 break; 03773 } 03774 } 03775 } 03776 } 03777 03778 /* If the bit depth < 8, it is expanded to 8. Also, if the already 03779 * expanded transparency value is supplied, an alpha channel is built. 03780 */ 03781 void /* PRIVATE */ 03782 png_do_expand(png_row_infop row_info, png_bytep row, 03783 png_color_16p trans_value) 03784 { 03785 int shift, value; 03786 png_bytep sp, dp; 03787 png_uint_32 i; 03788 png_uint_32 row_width=row_info->width; 03789 03790 png_debug(1, "in png_do_expand"); 03791 #if defined(PNG_USELESS_TESTS_SUPPORTED) 03792 if (row != NULL && row_info != NULL) 03793 #endif 03794 { 03795 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 03796 { 03797 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); 03798 03799 if (row_info->bit_depth < 8) 03800 { 03801 switch (row_info->bit_depth) 03802 { 03803 case 1: 03804 { 03805 gray = (png_uint_16)((gray&0x01)*0xff); 03806 sp = row + (png_size_t)((row_width - 1) >> 3); 03807 dp = row + (png_size_t)row_width - 1; 03808 shift = 7 - (int)((row_width + 7) & 0x07); 03809 for (i = 0; i < row_width; i++) 03810 { 03811 if ((*sp >> shift) & 0x01) 03812 *dp = 0xff; 03813 else 03814 *dp = 0; 03815 if (shift == 7) 03816 { 03817 shift = 0; 03818 sp--; 03819 } 03820 else 03821 shift++; 03822 03823 dp--; 03824 } 03825 break; 03826 } 03827 03828 case 2: 03829 { 03830 gray = (png_uint_16)((gray&0x03)*0x55); 03831 sp = row + (png_size_t)((row_width - 1) >> 2); 03832 dp = row + (png_size_t)row_width - 1; 03833 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 03834 for (i = 0; i < row_width; i++) 03835 { 03836 value = (*sp >> shift) & 0x03; 03837 *dp = (png_byte)(value | (value << 2) | (value << 4) | 03838 (value << 6)); 03839 if (shift == 6) 03840 { 03841 shift = 0; 03842 sp--; 03843 } 03844 else 03845 shift += 2; 03846 03847 dp--; 03848 } 03849 break; 03850 } 03851 03852 case 4: 03853 { 03854 gray = (png_uint_16)((gray&0x0f)*0x11); 03855 sp = row + (png_size_t)((row_width - 1) >> 1); 03856 dp = row + (png_size_t)row_width - 1; 03857 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 03858 for (i = 0; i < row_width; i++) 03859 { 03860 value = (*sp >> shift) & 0x0f; 03861 *dp = (png_byte)(value | (value << 4)); 03862 if (shift == 4) 03863 { 03864 shift = 0; 03865 sp--; 03866 } 03867 else 03868 shift = 4; 03869 03870 dp--; 03871 } 03872 break; 03873 } 03874 } 03875 03876 row_info->bit_depth = 8; 03877 row_info->pixel_depth = 8; 03878 row_info->rowbytes = row_width; 03879 } 03880 03881 if (trans_value != NULL) 03882 { 03883 if (row_info->bit_depth == 8) 03884 { 03885 gray = gray & 0xff; 03886 sp = row + (png_size_t)row_width - 1; 03887 dp = row + (png_size_t)(row_width << 1) - 1; 03888 for (i = 0; i < row_width; i++) 03889 { 03890 if (*sp == gray) 03891 *dp-- = 0; 03892 else 03893 *dp-- = 0xff; 03894 *dp-- = *sp--; 03895 } 03896 } 03897 03898 else if (row_info->bit_depth == 16) 03899 { 03900 png_byte gray_high = (gray >> 8) & 0xff; 03901 png_byte gray_low = gray & 0xff; 03902 sp = row + row_info->rowbytes - 1; 03903 dp = row + (row_info->rowbytes << 1) - 1; 03904 for (i = 0; i < row_width; i++) 03905 { 03906 if (*(sp - 1) == gray_high && *(sp) == gray_low) 03907 { 03908 *dp-- = 0; 03909 *dp-- = 0; 03910 } 03911 else 03912 { 03913 *dp-- = 0xff; 03914 *dp-- = 0xff; 03915 } 03916 *dp-- = *sp--; 03917 *dp-- = *sp--; 03918 } 03919 } 03920 03921 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 03922 row_info->channels = 2; 03923 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 03924 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 03925 row_width); 03926 } 03927 } 03928 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) 03929 { 03930 if (row_info->bit_depth == 8) 03931 { 03932 png_byte red = trans_value->red & 0xff; 03933 png_byte green = trans_value->green & 0xff; 03934 png_byte blue = trans_value->blue & 0xff; 03935 sp = row + (png_size_t)row_info->rowbytes - 1; 03936 dp = row + (png_size_t)(row_width << 2) - 1; 03937 for (i = 0; i < row_width; i++) 03938 { 03939 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 03940 *dp-- = 0; 03941 else 03942 *dp-- = 0xff; 03943 *dp-- = *sp--; 03944 *dp-- = *sp--; 03945 *dp-- = *sp--; 03946 } 03947 } 03948 else if (row_info->bit_depth == 16) 03949 { 03950 png_byte red_high = (trans_value->red >> 8) & 0xff; 03951 png_byte green_high = (trans_value->green >> 8) & 0xff; 03952 png_byte blue_high = (trans_value->blue >> 8) & 0xff; 03953 png_byte red_low = trans_value->red & 0xff; 03954 png_byte green_low = trans_value->green & 0xff; 03955 png_byte blue_low = trans_value->blue & 0xff; 03956 sp = row + row_info->rowbytes - 1; 03957 dp = row + (png_size_t)(row_width << 3) - 1; 03958 for (i = 0; i < row_width; i++) 03959 { 03960 if (*(sp - 5) == red_high && 03961 *(sp - 4) == red_low && 03962 *(sp - 3) == green_high && 03963 *(sp - 2) == green_low && 03964 *(sp - 1) == blue_high && 03965 *(sp ) == blue_low) 03966 { 03967 *dp-- = 0; 03968 *dp-- = 0; 03969 } 03970 else 03971 { 03972 *dp-- = 0xff; 03973 *dp-- = 0xff; 03974 } 03975 *dp-- = *sp--; 03976 *dp-- = *sp--; 03977 *dp-- = *sp--; 03978 *dp-- = *sp--; 03979 *dp-- = *sp--; 03980 *dp-- = *sp--; 03981 } 03982 } 03983 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 03984 row_info->channels = 4; 03985 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 03986 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 03987 } 03988 } 03989 } 03990 #endif 03991 03992 #if defined(PNG_READ_DITHER_SUPPORTED) 03993 void /* PRIVATE */ 03994 png_do_dither(png_row_infop row_info, png_bytep row, 03995 png_bytep palette_lookup, png_bytep dither_lookup) 03996 { 03997 png_bytep sp, dp; 03998 png_uint_32 i; 03999 png_uint_32 row_width=row_info->width; 04000 04001 png_debug(1, "in png_do_dither"); 04002 #if defined(PNG_USELESS_TESTS_SUPPORTED) 04003 if (row != NULL && row_info != NULL) 04004 #endif 04005 { 04006 if (row_info->color_type == PNG_COLOR_TYPE_RGB && 04007 palette_lookup && row_info->bit_depth == 8) 04008 { 04009 int r, g, b, p; 04010 sp = row; 04011 dp = row; 04012 for (i = 0; i < row_width; i++) 04013 { 04014 r = *sp++; 04015 g = *sp++; 04016 b = *sp++; 04017 04018 /* This looks real messy, but the compiler will reduce 04019 * it down to a reasonable formula. For example, with 04020 * 5 bits per color, we get: 04021 * p = (((r >> 3) & 0x1f) << 10) | 04022 * (((g >> 3) & 0x1f) << 5) | 04023 * ((b >> 3) & 0x1f); 04024 */ 04025 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 04026 ((1 << PNG_DITHER_RED_BITS) - 1)) << 04027 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 04028 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 04029 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 04030 (PNG_DITHER_BLUE_BITS)) | 04031 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 04032 ((1 << PNG_DITHER_BLUE_BITS) - 1)); 04033 04034 *dp++ = palette_lookup[p]; 04035 } 04036 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 04037 row_info->channels = 1; 04038 row_info->pixel_depth = row_info->bit_depth; 04039 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 04040 } 04041 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 04042 palette_lookup != NULL && row_info->bit_depth == 8) 04043 { 04044 int r, g, b, p; 04045 sp = row; 04046 dp = row; 04047 for (i = 0; i < row_width; i++) 04048 { 04049 r = *sp++; 04050 g = *sp++; 04051 b = *sp++; 04052 sp++; 04053 04054 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 04055 ((1 << PNG_DITHER_RED_BITS) - 1)) << 04056 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 04057 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 04058 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 04059 (PNG_DITHER_BLUE_BITS)) | 04060 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 04061 ((1 << PNG_DITHER_BLUE_BITS) - 1)); 04062 04063 *dp++ = palette_lookup[p]; 04064 } 04065 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 04066 row_info->channels = 1; 04067 row_info->pixel_depth = row_info->bit_depth; 04068 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 04069 } 04070 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 04071 dither_lookup && row_info->bit_depth == 8) 04072 { 04073 sp = row; 04074 for (i = 0; i < row_width; i++, sp++) 04075 { 04076 *sp = dither_lookup[*sp]; 04077 } 04078 } 04079 } 04080 } 04081 #endif 04082 04083 #ifdef PNG_FLOATING_POINT_SUPPORTED 04084 #if defined(PNG_READ_GAMMA_SUPPORTED) 04085 static PNG_CONST int png_gamma_shift[] = 04086 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; 04087 04088 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit 04089 * tables, we don't make a full table if we are reducing to 8-bit in 04090 * the future. Note also how the gamma_16 tables are segmented so that 04091 * we don't need to allocate > 64K chunks for a full 16-bit table. 04092 */ 04093 void /* PRIVATE */ 04094 png_build_gamma_table(png_structp png_ptr) 04095 { 04096 png_debug(1, "in png_build_gamma_table"); 04097 04098 if (png_ptr->bit_depth <= 8) 04099 { 04100 int i; 04101 double g; 04102 04103 if (png_ptr->screen_gamma > .000001) 04104 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 04105 04106 else 04107 g = 1.0; 04108 04109 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, 04110 (png_uint_32)256); 04111 04112 for (i = 0; i < 256; i++) 04113 { 04114 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, 04115 g) * 255.0 + .5); 04116 } 04117 04118 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 04119 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 04120 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) 04121 { 04122 04123 g = 1.0 / (png_ptr->gamma); 04124 04125 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, 04126 (png_uint_32)256); 04127 04128 for (i = 0; i < 256; i++) 04129 { 04130 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, 04131 g) * 255.0 + .5); 04132 } 04133 04134 04135 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, 04136 (png_uint_32)256); 04137 04138 if (png_ptr->screen_gamma > 0.000001) 04139 g = 1.0 / png_ptr->screen_gamma; 04140 04141 else 04142 g = png_ptr->gamma; /* Probably doing rgb_to_gray */ 04143 04144 for (i = 0; i < 256; i++) 04145 { 04146 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, 04147 g) * 255.0 + .5); 04148 04149 } 04150 } 04151 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 04152 } 04153 else 04154 { 04155 double g; 04156 int i, j, shift, num; 04157 int sig_bit; 04158 png_uint_32 ig; 04159 04160 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 04161 { 04162 sig_bit = (int)png_ptr->sig_bit.red; 04163 04164 if ((int)png_ptr->sig_bit.green > sig_bit) 04165 sig_bit = png_ptr->sig_bit.green; 04166 04167 if ((int)png_ptr->sig_bit.blue > sig_bit) 04168 sig_bit = png_ptr->sig_bit.blue; 04169 } 04170 else 04171 { 04172 sig_bit = (int)png_ptr->sig_bit.gray; 04173 } 04174 04175 if (sig_bit > 0) 04176 shift = 16 - sig_bit; 04177 04178 else 04179 shift = 0; 04180 04181 if (png_ptr->transformations & PNG_16_TO_8) 04182 { 04183 if (shift < (16 - PNG_MAX_GAMMA_8)) 04184 shift = (16 - PNG_MAX_GAMMA_8); 04185 } 04186 04187 if (shift > 8) 04188 shift = 8; 04189 04190 if (shift < 0) 04191 shift = 0; 04192 04193 png_ptr->gamma_shift = (png_byte)shift; 04194 04195 num = (1 << (8 - shift)); 04196 04197 if (png_ptr->screen_gamma > .000001) 04198 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 04199 else 04200 g = 1.0; 04201 04202 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, 04203 (png_uint_32)(num * png_sizeof(png_uint_16p))); 04204 png_memset(png_ptr->gamma_16_table, 0, num * png_sizeof(png_uint_16p)); 04205 04206 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) 04207 { 04208 double fin, fout; 04209 png_uint_32 last, max; 04210 04211 for (i = 0; i < num; i++) 04212 { 04213 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 04214 (png_uint_32)(256 * png_sizeof(png_uint_16))); 04215 } 04216 04217 g = 1.0 / g; 04218 last = 0; 04219 for (i = 0; i < 256; i++) 04220 { 04221 fout = ((double)i + 0.5) / 256.0; 04222 fin = pow(fout, g); 04223 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); 04224 while (last <= max) 04225 { 04226 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 04227 [(int)(last >> (8 - shift))] = (png_uint_16)( 04228 (png_uint_16)i | ((png_uint_16)i << 8)); 04229 last++; 04230 } 04231 } 04232 while (last < ((png_uint_32)num << 8)) 04233 { 04234 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 04235 [(int)(last >> (8 - shift))] = (png_uint_16)65535L; 04236 last++; 04237 } 04238 } 04239 else 04240 { 04241 for (i = 0; i < num; i++) 04242 { 04243 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 04244 (png_uint_32)(256 * png_sizeof(png_uint_16))); 04245 04246 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); 04247 04248 for (j = 0; j < 256; j++) 04249 { 04250 png_ptr->gamma_16_table[i][j] = 04251 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 04252 65535.0, g) * 65535.0 + .5); 04253 } 04254 } 04255 } 04256 04257 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 04258 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 04259 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) 04260 { 04261 04262 g = 1.0 / (png_ptr->gamma); 04263 04264 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, 04265 (png_uint_32)(num * png_sizeof(png_uint_16p ))); 04266 png_memset(png_ptr->gamma_16_to_1, 0, num * png_sizeof(png_uint_16p)); 04267 04268 for (i = 0; i < num; i++) 04269 { 04270 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, 04271 (png_uint_32)(256 * png_sizeof(png_uint_16))); 04272 04273 ig = (((png_uint_32)i * 04274 (png_uint_32)png_gamma_shift[shift]) >> 4); 04275 for (j = 0; j < 256; j++) 04276 { 04277 png_ptr->gamma_16_to_1[i][j] = 04278 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 04279 65535.0, g) * 65535.0 + .5); 04280 } 04281 } 04282 04283 if (png_ptr->screen_gamma > 0.000001) 04284 g = 1.0 / png_ptr->screen_gamma; 04285 04286 else 04287 g = png_ptr->gamma; /* Probably doing rgb_to_gray */ 04288 04289 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, 04290 (png_uint_32)(num * png_sizeof(png_uint_16p))); 04291 png_memset(png_ptr->gamma_16_from_1, 0, 04292 num * png_sizeof(png_uint_16p)); 04293 04294 for (i = 0; i < num; i++) 04295 { 04296 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, 04297 (png_uint_32)(256 * png_sizeof(png_uint_16))); 04298 04299 ig = (((png_uint_32)i * 04300 (png_uint_32)png_gamma_shift[shift]) >> 4); 04301 04302 for (j = 0; j < 256; j++) 04303 { 04304 png_ptr->gamma_16_from_1[i][j] = 04305 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 04306 65535.0, g) * 65535.0 + .5); 04307 } 04308 } 04309 } 04310 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 04311 } 04312 } 04313 #endif 04314 /* To do: install integer version of png_build_gamma_table here */ 04315 #endif 04316 04317 #if defined(PNG_MNG_FEATURES_SUPPORTED) 04318 /* Undoes intrapixel differencing */ 04319 void /* PRIVATE */ 04320 png_do_read_intrapixel(png_row_infop row_info, png_bytep row) 04321 { 04322 png_debug(1, "in png_do_read_intrapixel"); 04323 if ( 04324 #if defined(PNG_USELESS_TESTS_SUPPORTED) 04325 row != NULL && row_info != NULL && 04326 #endif 04327 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 04328 { 04329 int bytes_per_pixel; 04330 png_uint_32 row_width = row_info->width; 04331 if (row_info->bit_depth == 8) 04332 { 04333 png_bytep rp; 04334 png_uint_32 i; 04335 04336 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 04337 bytes_per_pixel = 3; 04338 04339 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 04340 bytes_per_pixel = 4; 04341 04342 else 04343 return; 04344 04345 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 04346 { 04347 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); 04348 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); 04349 } 04350 } 04351 else if (row_info->bit_depth == 16) 04352 { 04353 png_bytep rp; 04354 png_uint_32 i; 04355 04356 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 04357 bytes_per_pixel = 6; 04358 04359 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 04360 bytes_per_pixel = 8; 04361 04362 else 04363 return; 04364 04365 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 04366 { 04367 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 04368 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 04369 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 04370 png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); 04371 png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); 04372 *(rp ) = (png_byte)((red >> 8) & 0xff); 04373 *(rp+1) = (png_byte)(red & 0xff); 04374 *(rp+4) = (png_byte)((blue >> 8) & 0xff); 04375 *(rp+5) = (png_byte)(blue & 0xff); 04376 } 04377 } 04378 } 04379 } 04380 #endif /* PNG_MNG_FEATURES_SUPPORTED */ 04381 #endif /* PNG_READ_SUPPORTED */