3dphotoshoot
diff libs/libpng/pngrtran.c @ 14:06dc8b9b4f89
added libimago, libjpeg and libpng
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 07 Jun 2015 17:25:49 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/libpng/pngrtran.c Sun Jun 07 17:25:49 2015 +0300 1.3 @@ -0,0 +1,4296 @@ 1.4 + 1.5 +/* pngrtran.c - transforms the data in a row for PNG readers 1.6 + * 1.7 + * Last changed in libpng 1.2.30 [August 15, 2008] 1.8 + * For conditions of distribution and use, see copyright notice in png.h 1.9 + * Copyright (c) 1998-2008 Glenn Randers-Pehrson 1.10 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 1.11 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 1.12 + * 1.13 + * This file contains functions optionally called by an application 1.14 + * in order to tell libpng how to handle data when reading a PNG. 1.15 + * Transformations that are used in both reading and writing are 1.16 + * in pngtrans.c. 1.17 + */ 1.18 + 1.19 +#define PNG_INTERNAL 1.20 +#include "png.h" 1.21 +#if defined(PNG_READ_SUPPORTED) 1.22 + 1.23 +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ 1.24 +void PNGAPI 1.25 +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) 1.26 +{ 1.27 + png_debug(1, "in png_set_crc_action\n"); 1.28 + /* Tell libpng how we react to CRC errors in critical chunks */ 1.29 + if (png_ptr == NULL) return; 1.30 + switch (crit_action) 1.31 + { 1.32 + case PNG_CRC_NO_CHANGE: /* leave setting as is */ 1.33 + break; 1.34 + case PNG_CRC_WARN_USE: /* warn/use data */ 1.35 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.36 + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 1.37 + break; 1.38 + case PNG_CRC_QUIET_USE: /* quiet/use data */ 1.39 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.40 + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 1.41 + PNG_FLAG_CRC_CRITICAL_IGNORE; 1.42 + break; 1.43 + case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ 1.44 + png_warning(png_ptr, 1.45 + "Can't discard critical data on CRC error."); 1.46 + case PNG_CRC_ERROR_QUIT: /* error/quit */ 1.47 + case PNG_CRC_DEFAULT: 1.48 + default: 1.49 + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 1.50 + break; 1.51 + } 1.52 + 1.53 + switch (ancil_action) 1.54 + { 1.55 + case PNG_CRC_NO_CHANGE: /* leave setting as is */ 1.56 + break; 1.57 + case PNG_CRC_WARN_USE: /* warn/use data */ 1.58 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.59 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 1.60 + break; 1.61 + case PNG_CRC_QUIET_USE: /* quiet/use data */ 1.62 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.63 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 1.64 + PNG_FLAG_CRC_ANCILLARY_NOWARN; 1.65 + break; 1.66 + case PNG_CRC_ERROR_QUIT: /* error/quit */ 1.67 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.68 + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 1.69 + break; 1.70 + case PNG_CRC_WARN_DISCARD: /* warn/discard data */ 1.71 + case PNG_CRC_DEFAULT: 1.72 + default: 1.73 + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 1.74 + break; 1.75 + } 1.76 +} 1.77 + 1.78 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1.79 + defined(PNG_FLOATING_POINT_SUPPORTED) 1.80 +/* handle alpha and tRNS via a background color */ 1.81 +void PNGAPI 1.82 +png_set_background(png_structp png_ptr, 1.83 + png_color_16p background_color, int background_gamma_code, 1.84 + int need_expand, double background_gamma) 1.85 +{ 1.86 + png_debug(1, "in png_set_background\n"); 1.87 + if (png_ptr == NULL) return; 1.88 + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 1.89 + { 1.90 + png_warning(png_ptr, "Application must supply a known background gamma"); 1.91 + return; 1.92 + } 1.93 + 1.94 + png_ptr->transformations |= PNG_BACKGROUND; 1.95 + png_memcpy(&(png_ptr->background), background_color, 1.96 + png_sizeof(png_color_16)); 1.97 + png_ptr->background_gamma = (float)background_gamma; 1.98 + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 1.99 + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); 1.100 +} 1.101 +#endif 1.102 + 1.103 +#if defined(PNG_READ_16_TO_8_SUPPORTED) 1.104 +/* strip 16 bit depth files to 8 bit depth */ 1.105 +void PNGAPI 1.106 +png_set_strip_16(png_structp png_ptr) 1.107 +{ 1.108 + png_debug(1, "in png_set_strip_16\n"); 1.109 + if (png_ptr == NULL) return; 1.110 + png_ptr->transformations |= PNG_16_TO_8; 1.111 +} 1.112 +#endif 1.113 + 1.114 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 1.115 +void PNGAPI 1.116 +png_set_strip_alpha(png_structp png_ptr) 1.117 +{ 1.118 + png_debug(1, "in png_set_strip_alpha\n"); 1.119 + if (png_ptr == NULL) return; 1.120 + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; 1.121 +} 1.122 +#endif 1.123 + 1.124 +#if defined(PNG_READ_DITHER_SUPPORTED) 1.125 +/* Dither file to 8 bit. Supply a palette, the current number 1.126 + * of elements in the palette, the maximum number of elements 1.127 + * allowed, and a histogram if possible. If the current number 1.128 + * of colors is greater then the maximum number, the palette will be 1.129 + * modified to fit in the maximum number. "full_dither" indicates 1.130 + * whether we need a dithering cube set up for RGB images, or if we 1.131 + * simply are reducing the number of colors in a paletted image. 1.132 + */ 1.133 + 1.134 +typedef struct png_dsort_struct 1.135 +{ 1.136 + struct png_dsort_struct FAR * next; 1.137 + png_byte left; 1.138 + png_byte right; 1.139 +} png_dsort; 1.140 +typedef png_dsort FAR * png_dsortp; 1.141 +typedef png_dsort FAR * FAR * png_dsortpp; 1.142 + 1.143 +void PNGAPI 1.144 +png_set_dither(png_structp png_ptr, png_colorp palette, 1.145 + int num_palette, int maximum_colors, png_uint_16p histogram, 1.146 + int full_dither) 1.147 +{ 1.148 + png_debug(1, "in png_set_dither\n"); 1.149 + if (png_ptr == NULL) return; 1.150 + png_ptr->transformations |= PNG_DITHER; 1.151 + 1.152 + if (!full_dither) 1.153 + { 1.154 + int i; 1.155 + 1.156 + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, 1.157 + (png_uint_32)(num_palette * png_sizeof(png_byte))); 1.158 + for (i = 0; i < num_palette; i++) 1.159 + png_ptr->dither_index[i] = (png_byte)i; 1.160 + } 1.161 + 1.162 + if (num_palette > maximum_colors) 1.163 + { 1.164 + if (histogram != NULL) 1.165 + { 1.166 + /* This is easy enough, just throw out the least used colors. 1.167 + Perhaps not the best solution, but good enough. */ 1.168 + 1.169 + int i; 1.170 + 1.171 + /* initialize an array to sort colors */ 1.172 + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, 1.173 + (png_uint_32)(num_palette * png_sizeof(png_byte))); 1.174 + 1.175 + /* initialize the dither_sort array */ 1.176 + for (i = 0; i < num_palette; i++) 1.177 + png_ptr->dither_sort[i] = (png_byte)i; 1.178 + 1.179 + /* Find the least used palette entries by starting a 1.180 + bubble sort, and running it until we have sorted 1.181 + out enough colors. Note that we don't care about 1.182 + sorting all the colors, just finding which are 1.183 + least used. */ 1.184 + 1.185 + for (i = num_palette - 1; i >= maximum_colors; i--) 1.186 + { 1.187 + int done; /* to stop early if the list is pre-sorted */ 1.188 + int j; 1.189 + 1.190 + done = 1; 1.191 + for (j = 0; j < i; j++) 1.192 + { 1.193 + if (histogram[png_ptr->dither_sort[j]] 1.194 + < histogram[png_ptr->dither_sort[j + 1]]) 1.195 + { 1.196 + png_byte t; 1.197 + 1.198 + t = png_ptr->dither_sort[j]; 1.199 + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; 1.200 + png_ptr->dither_sort[j + 1] = t; 1.201 + done = 0; 1.202 + } 1.203 + } 1.204 + if (done) 1.205 + break; 1.206 + } 1.207 + 1.208 + /* swap the palette around, and set up a table, if necessary */ 1.209 + if (full_dither) 1.210 + { 1.211 + int j = num_palette; 1.212 + 1.213 + /* put all the useful colors within the max, but don't 1.214 + move the others */ 1.215 + for (i = 0; i < maximum_colors; i++) 1.216 + { 1.217 + if ((int)png_ptr->dither_sort[i] >= maximum_colors) 1.218 + { 1.219 + do 1.220 + j--; 1.221 + while ((int)png_ptr->dither_sort[j] >= maximum_colors); 1.222 + palette[i] = palette[j]; 1.223 + } 1.224 + } 1.225 + } 1.226 + else 1.227 + { 1.228 + int j = num_palette; 1.229 + 1.230 + /* move all the used colors inside the max limit, and 1.231 + develop a translation table */ 1.232 + for (i = 0; i < maximum_colors; i++) 1.233 + { 1.234 + /* only move the colors we need to */ 1.235 + if ((int)png_ptr->dither_sort[i] >= maximum_colors) 1.236 + { 1.237 + png_color tmp_color; 1.238 + 1.239 + do 1.240 + j--; 1.241 + while ((int)png_ptr->dither_sort[j] >= maximum_colors); 1.242 + 1.243 + tmp_color = palette[j]; 1.244 + palette[j] = palette[i]; 1.245 + palette[i] = tmp_color; 1.246 + /* indicate where the color went */ 1.247 + png_ptr->dither_index[j] = (png_byte)i; 1.248 + png_ptr->dither_index[i] = (png_byte)j; 1.249 + } 1.250 + } 1.251 + 1.252 + /* find closest color for those colors we are not using */ 1.253 + for (i = 0; i < num_palette; i++) 1.254 + { 1.255 + if ((int)png_ptr->dither_index[i] >= maximum_colors) 1.256 + { 1.257 + int min_d, k, min_k, d_index; 1.258 + 1.259 + /* find the closest color to one we threw out */ 1.260 + d_index = png_ptr->dither_index[i]; 1.261 + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 1.262 + for (k = 1, min_k = 0; k < maximum_colors; k++) 1.263 + { 1.264 + int d; 1.265 + 1.266 + d = PNG_COLOR_DIST(palette[d_index], palette[k]); 1.267 + 1.268 + if (d < min_d) 1.269 + { 1.270 + min_d = d; 1.271 + min_k = k; 1.272 + } 1.273 + } 1.274 + /* point to closest color */ 1.275 + png_ptr->dither_index[i] = (png_byte)min_k; 1.276 + } 1.277 + } 1.278 + } 1.279 + png_free(png_ptr, png_ptr->dither_sort); 1.280 + png_ptr->dither_sort = NULL; 1.281 + } 1.282 + else 1.283 + { 1.284 + /* This is much harder to do simply (and quickly). Perhaps 1.285 + we need to go through a median cut routine, but those 1.286 + don't always behave themselves with only a few colors 1.287 + as input. So we will just find the closest two colors, 1.288 + and throw out one of them (chosen somewhat randomly). 1.289 + [We don't understand this at all, so if someone wants to 1.290 + work on improving it, be our guest - AED, GRP] 1.291 + */ 1.292 + int i; 1.293 + int max_d; 1.294 + int num_new_palette; 1.295 + png_dsortp t; 1.296 + png_dsortpp hash; 1.297 + 1.298 + t = NULL; 1.299 + 1.300 + /* initialize palette index arrays */ 1.301 + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 1.302 + (png_uint_32)(num_palette * png_sizeof(png_byte))); 1.303 + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 1.304 + (png_uint_32)(num_palette * png_sizeof(png_byte))); 1.305 + 1.306 + /* initialize the sort array */ 1.307 + for (i = 0; i < num_palette; i++) 1.308 + { 1.309 + png_ptr->index_to_palette[i] = (png_byte)i; 1.310 + png_ptr->palette_to_index[i] = (png_byte)i; 1.311 + } 1.312 + 1.313 + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * 1.314 + png_sizeof(png_dsortp))); 1.315 + for (i = 0; i < 769; i++) 1.316 + hash[i] = NULL; 1.317 +/* png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); */ 1.318 + 1.319 + num_new_palette = num_palette; 1.320 + 1.321 + /* initial wild guess at how far apart the farthest pixel 1.322 + pair we will be eliminating will be. Larger 1.323 + numbers mean more areas will be allocated, Smaller 1.324 + numbers run the risk of not saving enough data, and 1.325 + having to do this all over again. 1.326 + 1.327 + I have not done extensive checking on this number. 1.328 + */ 1.329 + max_d = 96; 1.330 + 1.331 + while (num_new_palette > maximum_colors) 1.332 + { 1.333 + for (i = 0; i < num_new_palette - 1; i++) 1.334 + { 1.335 + int j; 1.336 + 1.337 + for (j = i + 1; j < num_new_palette; j++) 1.338 + { 1.339 + int d; 1.340 + 1.341 + d = PNG_COLOR_DIST(palette[i], palette[j]); 1.342 + 1.343 + if (d <= max_d) 1.344 + { 1.345 + 1.346 + t = (png_dsortp)png_malloc_warn(png_ptr, 1.347 + (png_uint_32)(png_sizeof(png_dsort))); 1.348 + if (t == NULL) 1.349 + break; 1.350 + t->next = hash[d]; 1.351 + t->left = (png_byte)i; 1.352 + t->right = (png_byte)j; 1.353 + hash[d] = t; 1.354 + } 1.355 + } 1.356 + if (t == NULL) 1.357 + break; 1.358 + } 1.359 + 1.360 + if (t != NULL) 1.361 + for (i = 0; i <= max_d; i++) 1.362 + { 1.363 + if (hash[i] != NULL) 1.364 + { 1.365 + png_dsortp p; 1.366 + 1.367 + for (p = hash[i]; p; p = p->next) 1.368 + { 1.369 + if ((int)png_ptr->index_to_palette[p->left] 1.370 + < num_new_palette && 1.371 + (int)png_ptr->index_to_palette[p->right] 1.372 + < num_new_palette) 1.373 + { 1.374 + int j, next_j; 1.375 + 1.376 + if (num_new_palette & 0x01) 1.377 + { 1.378 + j = p->left; 1.379 + next_j = p->right; 1.380 + } 1.381 + else 1.382 + { 1.383 + j = p->right; 1.384 + next_j = p->left; 1.385 + } 1.386 + 1.387 + num_new_palette--; 1.388 + palette[png_ptr->index_to_palette[j]] 1.389 + = palette[num_new_palette]; 1.390 + if (!full_dither) 1.391 + { 1.392 + int k; 1.393 + 1.394 + for (k = 0; k < num_palette; k++) 1.395 + { 1.396 + if (png_ptr->dither_index[k] == 1.397 + png_ptr->index_to_palette[j]) 1.398 + png_ptr->dither_index[k] = 1.399 + png_ptr->index_to_palette[next_j]; 1.400 + if ((int)png_ptr->dither_index[k] == 1.401 + num_new_palette) 1.402 + png_ptr->dither_index[k] = 1.403 + png_ptr->index_to_palette[j]; 1.404 + } 1.405 + } 1.406 + 1.407 + png_ptr->index_to_palette[png_ptr->palette_to_index 1.408 + [num_new_palette]] = png_ptr->index_to_palette[j]; 1.409 + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 1.410 + = png_ptr->palette_to_index[num_new_palette]; 1.411 + 1.412 + png_ptr->index_to_palette[j] = (png_byte)num_new_palette; 1.413 + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; 1.414 + } 1.415 + if (num_new_palette <= maximum_colors) 1.416 + break; 1.417 + } 1.418 + if (num_new_palette <= maximum_colors) 1.419 + break; 1.420 + } 1.421 + } 1.422 + 1.423 + for (i = 0; i < 769; i++) 1.424 + { 1.425 + if (hash[i] != NULL) 1.426 + { 1.427 + png_dsortp p = hash[i]; 1.428 + while (p) 1.429 + { 1.430 + t = p->next; 1.431 + png_free(png_ptr, p); 1.432 + p = t; 1.433 + } 1.434 + } 1.435 + hash[i] = 0; 1.436 + } 1.437 + max_d += 96; 1.438 + } 1.439 + png_free(png_ptr, hash); 1.440 + png_free(png_ptr, png_ptr->palette_to_index); 1.441 + png_free(png_ptr, png_ptr->index_to_palette); 1.442 + png_ptr->palette_to_index = NULL; 1.443 + png_ptr->index_to_palette = NULL; 1.444 + } 1.445 + num_palette = maximum_colors; 1.446 + } 1.447 + if (png_ptr->palette == NULL) 1.448 + { 1.449 + png_ptr->palette = palette; 1.450 + } 1.451 + png_ptr->num_palette = (png_uint_16)num_palette; 1.452 + 1.453 + if (full_dither) 1.454 + { 1.455 + int i; 1.456 + png_bytep distance; 1.457 + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + 1.458 + PNG_DITHER_BLUE_BITS; 1.459 + int num_red = (1 << PNG_DITHER_RED_BITS); 1.460 + int num_green = (1 << PNG_DITHER_GREEN_BITS); 1.461 + int num_blue = (1 << PNG_DITHER_BLUE_BITS); 1.462 + png_size_t num_entries = ((png_size_t)1 << total_bits); 1.463 + 1.464 + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, 1.465 + (png_uint_32)(num_entries * png_sizeof(png_byte))); 1.466 + 1.467 + png_memset(png_ptr->palette_lookup, 0, num_entries * 1.468 + png_sizeof(png_byte)); 1.469 + 1.470 + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 1.471 + png_sizeof(png_byte))); 1.472 + 1.473 + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); 1.474 + 1.475 + for (i = 0; i < num_palette; i++) 1.476 + { 1.477 + int ir, ig, ib; 1.478 + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); 1.479 + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); 1.480 + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); 1.481 + 1.482 + for (ir = 0; ir < num_red; ir++) 1.483 + { 1.484 + /* int dr = abs(ir - r); */ 1.485 + int dr = ((ir > r) ? ir - r : r - ir); 1.486 + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); 1.487 + 1.488 + for (ig = 0; ig < num_green; ig++) 1.489 + { 1.490 + /* int dg = abs(ig - g); */ 1.491 + int dg = ((ig > g) ? ig - g : g - ig); 1.492 + int dt = dr + dg; 1.493 + int dm = ((dr > dg) ? dr : dg); 1.494 + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); 1.495 + 1.496 + for (ib = 0; ib < num_blue; ib++) 1.497 + { 1.498 + int d_index = index_g | ib; 1.499 + /* int db = abs(ib - b); */ 1.500 + int db = ((ib > b) ? ib - b : b - ib); 1.501 + int dmax = ((dm > db) ? dm : db); 1.502 + int d = dmax + dt + db; 1.503 + 1.504 + if (d < (int)distance[d_index]) 1.505 + { 1.506 + distance[d_index] = (png_byte)d; 1.507 + png_ptr->palette_lookup[d_index] = (png_byte)i; 1.508 + } 1.509 + } 1.510 + } 1.511 + } 1.512 + } 1.513 + 1.514 + png_free(png_ptr, distance); 1.515 + } 1.516 +} 1.517 +#endif 1.518 + 1.519 +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 1.520 +/* Transform the image from the file_gamma to the screen_gamma. We 1.521 + * only do transformations on images where the file_gamma and screen_gamma 1.522 + * are not close reciprocals, otherwise it slows things down slightly, and 1.523 + * also needlessly introduces small errors. 1.524 + * 1.525 + * We will turn off gamma transformation later if no semitransparent entries 1.526 + * are present in the tRNS array for palette images. We can't do it here 1.527 + * because we don't necessarily have the tRNS chunk yet. 1.528 + */ 1.529 +void PNGAPI 1.530 +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) 1.531 +{ 1.532 + png_debug(1, "in png_set_gamma\n"); 1.533 + if (png_ptr == NULL) return; 1.534 + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || 1.535 + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || 1.536 + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 1.537 + png_ptr->transformations |= PNG_GAMMA; 1.538 + png_ptr->gamma = (float)file_gamma; 1.539 + png_ptr->screen_gamma = (float)scrn_gamma; 1.540 +} 1.541 +#endif 1.542 + 1.543 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.544 +/* Expand paletted images to RGB, expand grayscale images of 1.545 + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 1.546 + * to alpha channels. 1.547 + */ 1.548 +void PNGAPI 1.549 +png_set_expand(png_structp png_ptr) 1.550 +{ 1.551 + png_debug(1, "in png_set_expand\n"); 1.552 + if (png_ptr == NULL) return; 1.553 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.554 + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 1.555 +} 1.556 + 1.557 +/* GRR 19990627: the following three functions currently are identical 1.558 + * to png_set_expand(). However, it is entirely reasonable that someone 1.559 + * might wish to expand an indexed image to RGB but *not* expand a single, 1.560 + * fully transparent palette entry to a full alpha channel--perhaps instead 1.561 + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 1.562 + * the transparent color with a particular RGB value, or drop tRNS entirely. 1.563 + * IOW, a future version of the library may make the transformations flag 1.564 + * a bit more fine-grained, with separate bits for each of these three 1.565 + * functions. 1.566 + * 1.567 + * More to the point, these functions make it obvious what libpng will be 1.568 + * doing, whereas "expand" can (and does) mean any number of things. 1.569 + * 1.570 + * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified 1.571 + * to expand only the sample depth but not to expand the tRNS to alpha. 1.572 + */ 1.573 + 1.574 +/* Expand paletted images to RGB. */ 1.575 +void PNGAPI 1.576 +png_set_palette_to_rgb(png_structp png_ptr) 1.577 +{ 1.578 + png_debug(1, "in png_set_palette_to_rgb\n"); 1.579 + if (png_ptr == NULL) return; 1.580 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.581 + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 1.582 +} 1.583 + 1.584 +#if !defined(PNG_1_0_X) 1.585 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ 1.586 +void PNGAPI 1.587 +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) 1.588 +{ 1.589 + png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n"); 1.590 + if (png_ptr == NULL) return; 1.591 + png_ptr->transformations |= PNG_EXPAND; 1.592 + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 1.593 +} 1.594 +#endif 1.595 + 1.596 +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) 1.597 +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ 1.598 +/* Deprecated as of libpng-1.2.9 */ 1.599 +void PNGAPI 1.600 +png_set_gray_1_2_4_to_8(png_structp png_ptr) 1.601 +{ 1.602 + png_debug(1, "in png_set_gray_1_2_4_to_8\n"); 1.603 + if (png_ptr == NULL) return; 1.604 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.605 +} 1.606 +#endif 1.607 + 1.608 + 1.609 +/* Expand tRNS chunks to alpha channels. */ 1.610 +void PNGAPI 1.611 +png_set_tRNS_to_alpha(png_structp png_ptr) 1.612 +{ 1.613 + png_debug(1, "in png_set_tRNS_to_alpha\n"); 1.614 + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 1.615 + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 1.616 +} 1.617 +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ 1.618 + 1.619 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.620 +void PNGAPI 1.621 +png_set_gray_to_rgb(png_structp png_ptr) 1.622 +{ 1.623 + png_debug(1, "in png_set_gray_to_rgb\n"); 1.624 + png_ptr->transformations |= PNG_GRAY_TO_RGB; 1.625 + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 1.626 +} 1.627 +#endif 1.628 + 1.629 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.630 +#if defined(PNG_FLOATING_POINT_SUPPORTED) 1.631 +/* Convert a RGB image to a grayscale of the same width. This allows us, 1.632 + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 1.633 + */ 1.634 + 1.635 +void PNGAPI 1.636 +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, 1.637 + double green) 1.638 +{ 1.639 + int red_fixed = (int)((float)red*100000.0 + 0.5); 1.640 + int green_fixed = (int)((float)green*100000.0 + 0.5); 1.641 + if (png_ptr == NULL) return; 1.642 + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); 1.643 +} 1.644 +#endif 1.645 + 1.646 +void PNGAPI 1.647 +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, 1.648 + png_fixed_point red, png_fixed_point green) 1.649 +{ 1.650 + png_debug(1, "in png_set_rgb_to_gray\n"); 1.651 + if (png_ptr == NULL) return; 1.652 + switch(error_action) 1.653 + { 1.654 + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; 1.655 + break; 1.656 + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 1.657 + break; 1.658 + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 1.659 + } 1.660 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.661 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.662 + png_ptr->transformations |= PNG_EXPAND; 1.663 +#else 1.664 + { 1.665 + png_warning(png_ptr, 1.666 + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); 1.667 + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; 1.668 + } 1.669 +#endif 1.670 + { 1.671 + png_uint_16 red_int, green_int; 1.672 + if (red < 0 || green < 0) 1.673 + { 1.674 + red_int = 6968; /* .212671 * 32768 + .5 */ 1.675 + green_int = 23434; /* .715160 * 32768 + .5 */ 1.676 + } 1.677 + else if (red + green < 100000L) 1.678 + { 1.679 + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); 1.680 + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); 1.681 + } 1.682 + else 1.683 + { 1.684 + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); 1.685 + red_int = 6968; 1.686 + green_int = 23434; 1.687 + } 1.688 + png_ptr->rgb_to_gray_red_coeff = red_int; 1.689 + png_ptr->rgb_to_gray_green_coeff = green_int; 1.690 + png_ptr->rgb_to_gray_blue_coeff = 1.691 + (png_uint_16)(32768 - red_int - green_int); 1.692 + } 1.693 +} 1.694 +#endif 1.695 + 1.696 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 1.697 + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ 1.698 + defined(PNG_LEGACY_SUPPORTED) 1.699 +void PNGAPI 1.700 +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr 1.701 + read_user_transform_fn) 1.702 +{ 1.703 + png_debug(1, "in png_set_read_user_transform_fn\n"); 1.704 + if (png_ptr == NULL) return; 1.705 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 1.706 + png_ptr->transformations |= PNG_USER_TRANSFORM; 1.707 + png_ptr->read_user_transform_fn = read_user_transform_fn; 1.708 +#endif 1.709 +#ifdef PNG_LEGACY_SUPPORTED 1.710 + if (read_user_transform_fn) 1.711 + png_warning(png_ptr, 1.712 + "This version of libpng does not support user transforms"); 1.713 +#endif 1.714 +} 1.715 +#endif 1.716 + 1.717 +/* Initialize everything needed for the read. This includes modifying 1.718 + * the palette. 1.719 + */ 1.720 +void /* PRIVATE */ 1.721 +png_init_read_transformations(png_structp png_ptr) 1.722 +{ 1.723 + png_debug(1, "in png_init_read_transformations\n"); 1.724 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.725 + if (png_ptr != NULL) 1.726 +#endif 1.727 + { 1.728 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ 1.729 + || defined(PNG_READ_GAMMA_SUPPORTED) 1.730 + int color_type = png_ptr->color_type; 1.731 +#endif 1.732 + 1.733 +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 1.734 + 1.735 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.736 + /* Detect gray background and attempt to enable optimization 1.737 + * for gray --> RGB case */ 1.738 + /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 1.739 + * RGB_ALPHA (in which case need_expand is superfluous anyway), the 1.740 + * background color might actually be gray yet not be flagged as such. 1.741 + * This is not a problem for the current code, which uses 1.742 + * PNG_BACKGROUND_IS_GRAY only to decide when to do the 1.743 + * png_do_gray_to_rgb() transformation. 1.744 + */ 1.745 + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.746 + !(color_type & PNG_COLOR_MASK_COLOR)) 1.747 + { 1.748 + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1.749 + } else if ((png_ptr->transformations & PNG_BACKGROUND) && 1.750 + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.751 + (png_ptr->transformations & PNG_GRAY_TO_RGB) && 1.752 + png_ptr->background.red == png_ptr->background.green && 1.753 + png_ptr->background.red == png_ptr->background.blue) 1.754 + { 1.755 + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 1.756 + png_ptr->background.gray = png_ptr->background.red; 1.757 + } 1.758 +#endif 1.759 + 1.760 + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 1.761 + (png_ptr->transformations & PNG_EXPAND)) 1.762 + { 1.763 + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ 1.764 + { 1.765 + /* expand background and tRNS chunks */ 1.766 + switch (png_ptr->bit_depth) 1.767 + { 1.768 + case 1: 1.769 + png_ptr->background.gray *= (png_uint_16)0xff; 1.770 + png_ptr->background.red = png_ptr->background.green 1.771 + = png_ptr->background.blue = png_ptr->background.gray; 1.772 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.773 + { 1.774 + png_ptr->trans_values.gray *= (png_uint_16)0xff; 1.775 + png_ptr->trans_values.red = png_ptr->trans_values.green 1.776 + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 1.777 + } 1.778 + break; 1.779 + case 2: 1.780 + png_ptr->background.gray *= (png_uint_16)0x55; 1.781 + png_ptr->background.red = png_ptr->background.green 1.782 + = png_ptr->background.blue = png_ptr->background.gray; 1.783 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.784 + { 1.785 + png_ptr->trans_values.gray *= (png_uint_16)0x55; 1.786 + png_ptr->trans_values.red = png_ptr->trans_values.green 1.787 + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 1.788 + } 1.789 + break; 1.790 + case 4: 1.791 + png_ptr->background.gray *= (png_uint_16)0x11; 1.792 + png_ptr->background.red = png_ptr->background.green 1.793 + = png_ptr->background.blue = png_ptr->background.gray; 1.794 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.795 + { 1.796 + png_ptr->trans_values.gray *= (png_uint_16)0x11; 1.797 + png_ptr->trans_values.red = png_ptr->trans_values.green 1.798 + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 1.799 + } 1.800 + break; 1.801 + case 8: 1.802 + case 16: 1.803 + png_ptr->background.red = png_ptr->background.green 1.804 + = png_ptr->background.blue = png_ptr->background.gray; 1.805 + break; 1.806 + } 1.807 + } 1.808 + else if (color_type == PNG_COLOR_TYPE_PALETTE) 1.809 + { 1.810 + png_ptr->background.red = 1.811 + png_ptr->palette[png_ptr->background.index].red; 1.812 + png_ptr->background.green = 1.813 + png_ptr->palette[png_ptr->background.index].green; 1.814 + png_ptr->background.blue = 1.815 + png_ptr->palette[png_ptr->background.index].blue; 1.816 + 1.817 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 1.818 + if (png_ptr->transformations & PNG_INVERT_ALPHA) 1.819 + { 1.820 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.821 + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 1.822 +#endif 1.823 + { 1.824 + /* invert the alpha channel (in tRNS) unless the pixels are 1.825 + going to be expanded, in which case leave it for later */ 1.826 + int i, istop; 1.827 + istop=(int)png_ptr->num_trans; 1.828 + for (i=0; i<istop; i++) 1.829 + png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); 1.830 + } 1.831 + } 1.832 +#endif 1.833 + 1.834 + } 1.835 + } 1.836 +#endif 1.837 + 1.838 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) 1.839 + png_ptr->background_1 = png_ptr->background; 1.840 +#endif 1.841 +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 1.842 + 1.843 + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) 1.844 + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) 1.845 + < PNG_GAMMA_THRESHOLD)) 1.846 + { 1.847 + int i, k; 1.848 + k=0; 1.849 + for (i=0; i<png_ptr->num_trans; i++) 1.850 + { 1.851 + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) 1.852 + k=1; /* partial transparency is present */ 1.853 + } 1.854 + if (k == 0) 1.855 + png_ptr->transformations &= ~PNG_GAMMA; 1.856 + } 1.857 + 1.858 + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && 1.859 + png_ptr->gamma != 0.0) 1.860 + { 1.861 + png_build_gamma_table(png_ptr); 1.862 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.863 + if (png_ptr->transformations & PNG_BACKGROUND) 1.864 + { 1.865 + if (color_type == PNG_COLOR_TYPE_PALETTE) 1.866 + { 1.867 + /* could skip if no transparency and 1.868 + */ 1.869 + png_color back, back_1; 1.870 + png_colorp palette = png_ptr->palette; 1.871 + int num_palette = png_ptr->num_palette; 1.872 + int i; 1.873 + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 1.874 + { 1.875 + back.red = png_ptr->gamma_table[png_ptr->background.red]; 1.876 + back.green = png_ptr->gamma_table[png_ptr->background.green]; 1.877 + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 1.878 + 1.879 + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 1.880 + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 1.881 + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 1.882 + } 1.883 + else 1.884 + { 1.885 + double g, gs; 1.886 + 1.887 + switch (png_ptr->background_gamma_type) 1.888 + { 1.889 + case PNG_BACKGROUND_GAMMA_SCREEN: 1.890 + g = (png_ptr->screen_gamma); 1.891 + gs = 1.0; 1.892 + break; 1.893 + case PNG_BACKGROUND_GAMMA_FILE: 1.894 + g = 1.0 / (png_ptr->gamma); 1.895 + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 1.896 + break; 1.897 + case PNG_BACKGROUND_GAMMA_UNIQUE: 1.898 + g = 1.0 / (png_ptr->background_gamma); 1.899 + gs = 1.0 / (png_ptr->background_gamma * 1.900 + png_ptr->screen_gamma); 1.901 + break; 1.902 + default: 1.903 + g = 1.0; /* back_1 */ 1.904 + gs = 1.0; /* back */ 1.905 + } 1.906 + 1.907 + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) 1.908 + { 1.909 + back.red = (png_byte)png_ptr->background.red; 1.910 + back.green = (png_byte)png_ptr->background.green; 1.911 + back.blue = (png_byte)png_ptr->background.blue; 1.912 + } 1.913 + else 1.914 + { 1.915 + back.red = (png_byte)(pow( 1.916 + (double)png_ptr->background.red/255, gs) * 255.0 + .5); 1.917 + back.green = (png_byte)(pow( 1.918 + (double)png_ptr->background.green/255, gs) * 255.0 + .5); 1.919 + back.blue = (png_byte)(pow( 1.920 + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); 1.921 + } 1.922 + 1.923 + back_1.red = (png_byte)(pow( 1.924 + (double)png_ptr->background.red/255, g) * 255.0 + .5); 1.925 + back_1.green = (png_byte)(pow( 1.926 + (double)png_ptr->background.green/255, g) * 255.0 + .5); 1.927 + back_1.blue = (png_byte)(pow( 1.928 + (double)png_ptr->background.blue/255, g) * 255.0 + .5); 1.929 + } 1.930 + for (i = 0; i < num_palette; i++) 1.931 + { 1.932 + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) 1.933 + { 1.934 + if (png_ptr->trans[i] == 0) 1.935 + { 1.936 + palette[i] = back; 1.937 + } 1.938 + else /* if (png_ptr->trans[i] != 0xff) */ 1.939 + { 1.940 + png_byte v, w; 1.941 + 1.942 + v = png_ptr->gamma_to_1[palette[i].red]; 1.943 + png_composite(w, v, png_ptr->trans[i], back_1.red); 1.944 + palette[i].red = png_ptr->gamma_from_1[w]; 1.945 + 1.946 + v = png_ptr->gamma_to_1[palette[i].green]; 1.947 + png_composite(w, v, png_ptr->trans[i], back_1.green); 1.948 + palette[i].green = png_ptr->gamma_from_1[w]; 1.949 + 1.950 + v = png_ptr->gamma_to_1[palette[i].blue]; 1.951 + png_composite(w, v, png_ptr->trans[i], back_1.blue); 1.952 + palette[i].blue = png_ptr->gamma_from_1[w]; 1.953 + } 1.954 + } 1.955 + else 1.956 + { 1.957 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.958 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.959 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.960 + } 1.961 + } 1.962 + /* Prevent the transformations being done again, and make sure 1.963 + * that the now spurious alpha channel is stripped - the code 1.964 + * has just reduced background composition and gamma correction 1.965 + * to a simple alpha channel strip. 1.966 + */ 1.967 + png_ptr->transformations &= ~PNG_BACKGROUND; 1.968 + png_ptr->transformations &= ~PNG_GAMMA; 1.969 + png_ptr->transformations |= PNG_STRIP_ALPHA; 1.970 + } 1.971 + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 1.972 + else 1.973 + /* color_type != PNG_COLOR_TYPE_PALETTE */ 1.974 + { 1.975 + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); 1.976 + double g = 1.0; 1.977 + double gs = 1.0; 1.978 + 1.979 + switch (png_ptr->background_gamma_type) 1.980 + { 1.981 + case PNG_BACKGROUND_GAMMA_SCREEN: 1.982 + g = (png_ptr->screen_gamma); 1.983 + gs = 1.0; 1.984 + break; 1.985 + case PNG_BACKGROUND_GAMMA_FILE: 1.986 + g = 1.0 / (png_ptr->gamma); 1.987 + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 1.988 + break; 1.989 + case PNG_BACKGROUND_GAMMA_UNIQUE: 1.990 + g = 1.0 / (png_ptr->background_gamma); 1.991 + gs = 1.0 / (png_ptr->background_gamma * 1.992 + png_ptr->screen_gamma); 1.993 + break; 1.994 + } 1.995 + 1.996 + png_ptr->background_1.gray = (png_uint_16)(pow( 1.997 + (double)png_ptr->background.gray / m, g) * m + .5); 1.998 + png_ptr->background.gray = (png_uint_16)(pow( 1.999 + (double)png_ptr->background.gray / m, gs) * m + .5); 1.1000 + 1.1001 + if ((png_ptr->background.red != png_ptr->background.green) || 1.1002 + (png_ptr->background.red != png_ptr->background.blue) || 1.1003 + (png_ptr->background.red != png_ptr->background.gray)) 1.1004 + { 1.1005 + /* RGB or RGBA with color background */ 1.1006 + png_ptr->background_1.red = (png_uint_16)(pow( 1.1007 + (double)png_ptr->background.red / m, g) * m + .5); 1.1008 + png_ptr->background_1.green = (png_uint_16)(pow( 1.1009 + (double)png_ptr->background.green / m, g) * m + .5); 1.1010 + png_ptr->background_1.blue = (png_uint_16)(pow( 1.1011 + (double)png_ptr->background.blue / m, g) * m + .5); 1.1012 + png_ptr->background.red = (png_uint_16)(pow( 1.1013 + (double)png_ptr->background.red / m, gs) * m + .5); 1.1014 + png_ptr->background.green = (png_uint_16)(pow( 1.1015 + (double)png_ptr->background.green / m, gs) * m + .5); 1.1016 + png_ptr->background.blue = (png_uint_16)(pow( 1.1017 + (double)png_ptr->background.blue / m, gs) * m + .5); 1.1018 + } 1.1019 + else 1.1020 + { 1.1021 + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 1.1022 + png_ptr->background_1.red = png_ptr->background_1.green 1.1023 + = png_ptr->background_1.blue = png_ptr->background_1.gray; 1.1024 + png_ptr->background.red = png_ptr->background.green 1.1025 + = png_ptr->background.blue = png_ptr->background.gray; 1.1026 + } 1.1027 + } 1.1028 + } 1.1029 + else 1.1030 + /* transformation does not include PNG_BACKGROUND */ 1.1031 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1.1032 + if (color_type == PNG_COLOR_TYPE_PALETTE) 1.1033 + { 1.1034 + png_colorp palette = png_ptr->palette; 1.1035 + int num_palette = png_ptr->num_palette; 1.1036 + int i; 1.1037 + 1.1038 + for (i = 0; i < num_palette; i++) 1.1039 + { 1.1040 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.1041 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.1042 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.1043 + } 1.1044 + 1.1045 + /* Done the gamma correction. */ 1.1046 + png_ptr->transformations &= ~PNG_GAMMA; 1.1047 + } 1.1048 + } 1.1049 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1050 + else 1.1051 +#endif 1.1052 +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ 1.1053 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1054 + /* No GAMMA transformation */ 1.1055 + if ((png_ptr->transformations & PNG_BACKGROUND) && 1.1056 + (color_type == PNG_COLOR_TYPE_PALETTE)) 1.1057 + { 1.1058 + int i; 1.1059 + int istop = (int)png_ptr->num_trans; 1.1060 + png_color back; 1.1061 + png_colorp palette = png_ptr->palette; 1.1062 + 1.1063 + back.red = (png_byte)png_ptr->background.red; 1.1064 + back.green = (png_byte)png_ptr->background.green; 1.1065 + back.blue = (png_byte)png_ptr->background.blue; 1.1066 + 1.1067 + for (i = 0; i < istop; i++) 1.1068 + { 1.1069 + if (png_ptr->trans[i] == 0) 1.1070 + { 1.1071 + palette[i] = back; 1.1072 + } 1.1073 + else if (png_ptr->trans[i] != 0xff) 1.1074 + { 1.1075 + /* The png_composite() macro is defined in png.h */ 1.1076 + png_composite(palette[i].red, palette[i].red, 1.1077 + png_ptr->trans[i], back.red); 1.1078 + png_composite(palette[i].green, palette[i].green, 1.1079 + png_ptr->trans[i], back.green); 1.1080 + png_composite(palette[i].blue, palette[i].blue, 1.1081 + png_ptr->trans[i], back.blue); 1.1082 + } 1.1083 + } 1.1084 + 1.1085 + /* Handled alpha, still need to strip the channel. */ 1.1086 + png_ptr->transformations &= ~PNG_BACKGROUND; 1.1087 + png_ptr->transformations |= PNG_STRIP_ALPHA; 1.1088 + } 1.1089 +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1.1090 + 1.1091 +#if defined(PNG_READ_SHIFT_SUPPORTED) 1.1092 + if ((png_ptr->transformations & PNG_SHIFT) && 1.1093 + (color_type == PNG_COLOR_TYPE_PALETTE)) 1.1094 + { 1.1095 + png_uint_16 i; 1.1096 + png_uint_16 istop = png_ptr->num_palette; 1.1097 + int sr = 8 - png_ptr->sig_bit.red; 1.1098 + int sg = 8 - png_ptr->sig_bit.green; 1.1099 + int sb = 8 - png_ptr->sig_bit.blue; 1.1100 + 1.1101 + if (sr < 0 || sr > 8) 1.1102 + sr = 0; 1.1103 + if (sg < 0 || sg > 8) 1.1104 + sg = 0; 1.1105 + if (sb < 0 || sb > 8) 1.1106 + sb = 0; 1.1107 + for (i = 0; i < istop; i++) 1.1108 + { 1.1109 + png_ptr->palette[i].red >>= sr; 1.1110 + png_ptr->palette[i].green >>= sg; 1.1111 + png_ptr->palette[i].blue >>= sb; 1.1112 + } 1.1113 + } 1.1114 +#endif /* PNG_READ_SHIFT_SUPPORTED */ 1.1115 + } 1.1116 +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ 1.1117 + && !defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1118 + if (png_ptr) 1.1119 + return; 1.1120 +#endif 1.1121 +} 1.1122 + 1.1123 +/* Modify the info structure to reflect the transformations. The 1.1124 + * info should be updated so a PNG file could be written with it, 1.1125 + * assuming the transformations result in valid PNG data. 1.1126 + */ 1.1127 +void /* PRIVATE */ 1.1128 +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) 1.1129 +{ 1.1130 + png_debug(1, "in png_read_transform_info\n"); 1.1131 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.1132 + if (png_ptr->transformations & PNG_EXPAND) 1.1133 + { 1.1134 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.1135 + { 1.1136 + if (png_ptr->num_trans && 1.1137 + (png_ptr->transformations & PNG_EXPAND_tRNS)) 1.1138 + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1.1139 + else 1.1140 + info_ptr->color_type = PNG_COLOR_TYPE_RGB; 1.1141 + info_ptr->bit_depth = 8; 1.1142 + info_ptr->num_trans = 0; 1.1143 + } 1.1144 + else 1.1145 + { 1.1146 + if (png_ptr->num_trans) 1.1147 + { 1.1148 + if (png_ptr->transformations & PNG_EXPAND_tRNS) 1.1149 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1.1150 +#if 0 /* Removed from libpng-1.2.27 */ 1.1151 + else 1.1152 + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; 1.1153 +#endif 1.1154 + } 1.1155 + if (info_ptr->bit_depth < 8) 1.1156 + info_ptr->bit_depth = 8; 1.1157 + info_ptr->num_trans = 0; 1.1158 + } 1.1159 + } 1.1160 +#endif 1.1161 + 1.1162 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1163 + if (png_ptr->transformations & PNG_BACKGROUND) 1.1164 + { 1.1165 + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 1.1166 + info_ptr->num_trans = 0; 1.1167 + info_ptr->background = png_ptr->background; 1.1168 + } 1.1169 +#endif 1.1170 + 1.1171 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.1172 + if (png_ptr->transformations & PNG_GAMMA) 1.1173 + { 1.1174 +#ifdef PNG_FLOATING_POINT_SUPPORTED 1.1175 + info_ptr->gamma = png_ptr->gamma; 1.1176 +#endif 1.1177 +#ifdef PNG_FIXED_POINT_SUPPORTED 1.1178 + info_ptr->int_gamma = png_ptr->int_gamma; 1.1179 +#endif 1.1180 + } 1.1181 +#endif 1.1182 + 1.1183 +#if defined(PNG_READ_16_TO_8_SUPPORTED) 1.1184 + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) 1.1185 + info_ptr->bit_depth = 8; 1.1186 +#endif 1.1187 + 1.1188 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.1189 + if (png_ptr->transformations & PNG_GRAY_TO_RGB) 1.1190 + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; 1.1191 +#endif 1.1192 + 1.1193 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.1194 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.1195 + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; 1.1196 +#endif 1.1197 + 1.1198 +#if defined(PNG_READ_DITHER_SUPPORTED) 1.1199 + if (png_ptr->transformations & PNG_DITHER) 1.1200 + { 1.1201 + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1.1202 + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 1.1203 + png_ptr->palette_lookup && info_ptr->bit_depth == 8) 1.1204 + { 1.1205 + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 1.1206 + } 1.1207 + } 1.1208 +#endif 1.1209 + 1.1210 +#if defined(PNG_READ_PACK_SUPPORTED) 1.1211 + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) 1.1212 + info_ptr->bit_depth = 8; 1.1213 +#endif 1.1214 + 1.1215 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.1216 + info_ptr->channels = 1; 1.1217 + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 1.1218 + info_ptr->channels = 3; 1.1219 + else 1.1220 + info_ptr->channels = 1; 1.1221 + 1.1222 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 1.1223 + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 1.1224 + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 1.1225 +#endif 1.1226 + 1.1227 + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 1.1228 + info_ptr->channels++; 1.1229 + 1.1230 +#if defined(PNG_READ_FILLER_SUPPORTED) 1.1231 + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 1.1232 + if ((png_ptr->transformations & PNG_FILLER) && 1.1233 + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1.1234 + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) 1.1235 + { 1.1236 + info_ptr->channels++; 1.1237 + /* if adding a true alpha channel not just filler */ 1.1238 +#if !defined(PNG_1_0_X) 1.1239 + if (png_ptr->transformations & PNG_ADD_ALPHA) 1.1240 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1.1241 +#endif 1.1242 + } 1.1243 +#endif 1.1244 + 1.1245 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 1.1246 +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 1.1247 + if (png_ptr->transformations & PNG_USER_TRANSFORM) 1.1248 + { 1.1249 + if (info_ptr->bit_depth < png_ptr->user_transform_depth) 1.1250 + info_ptr->bit_depth = png_ptr->user_transform_depth; 1.1251 + if (info_ptr->channels < png_ptr->user_transform_channels) 1.1252 + info_ptr->channels = png_ptr->user_transform_channels; 1.1253 + } 1.1254 +#endif 1.1255 + 1.1256 + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 1.1257 + info_ptr->bit_depth); 1.1258 + 1.1259 + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 1.1260 + 1.1261 +#if !defined(PNG_READ_EXPAND_SUPPORTED) 1.1262 + if (png_ptr) 1.1263 + return; 1.1264 +#endif 1.1265 +} 1.1266 + 1.1267 +/* Transform the row. The order of transformations is significant, 1.1268 + * and is very touchy. If you add a transformation, take care to 1.1269 + * decide how it fits in with the other transformations here. 1.1270 + */ 1.1271 +void /* PRIVATE */ 1.1272 +png_do_read_transformations(png_structp png_ptr) 1.1273 +{ 1.1274 + png_debug(1, "in png_do_read_transformations\n"); 1.1275 + if (png_ptr->row_buf == NULL) 1.1276 + { 1.1277 +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 1.1278 + char msg[50]; 1.1279 + 1.1280 + png_snprintf2(msg, 50, 1.1281 + "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, 1.1282 + png_ptr->pass); 1.1283 + png_error(png_ptr, msg); 1.1284 +#else 1.1285 + png_error(png_ptr, "NULL row buffer"); 1.1286 +#endif 1.1287 + } 1.1288 +#ifdef PNG_WARN_UNINITIALIZED_ROW 1.1289 + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 1.1290 + /* Application has failed to call either png_read_start_image() 1.1291 + * or png_read_update_info() after setting transforms that expand 1.1292 + * pixels. This check added to libpng-1.2.19 */ 1.1293 +#if (PNG_WARN_UNINITIALIZED_ROW==1) 1.1294 + png_error(png_ptr, "Uninitialized row"); 1.1295 +#else 1.1296 + png_warning(png_ptr, "Uninitialized row"); 1.1297 +#endif 1.1298 +#endif 1.1299 + 1.1300 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.1301 + if (png_ptr->transformations & PNG_EXPAND) 1.1302 + { 1.1303 + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) 1.1304 + { 1.1305 + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1306 + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); 1.1307 + } 1.1308 + else 1.1309 + { 1.1310 + if (png_ptr->num_trans && 1.1311 + (png_ptr->transformations & PNG_EXPAND_tRNS)) 1.1312 + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1313 + &(png_ptr->trans_values)); 1.1314 + else 1.1315 + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1316 + NULL); 1.1317 + } 1.1318 + } 1.1319 +#endif 1.1320 + 1.1321 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 1.1322 + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 1.1323 + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1324 + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); 1.1325 +#endif 1.1326 + 1.1327 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.1328 + if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1.1329 + { 1.1330 + int rgb_error = 1.1331 + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); 1.1332 + if (rgb_error) 1.1333 + { 1.1334 + png_ptr->rgb_to_gray_status=1; 1.1335 + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1.1336 + PNG_RGB_TO_GRAY_WARN) 1.1337 + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1.1338 + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1.1339 + PNG_RGB_TO_GRAY_ERR) 1.1340 + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1.1341 + } 1.1342 + } 1.1343 +#endif 1.1344 + 1.1345 +/* 1.1346 +From Andreas Dilger e-mail to png-implement, 26 March 1998: 1.1347 + 1.1348 + In most cases, the "simple transparency" should be done prior to doing 1.1349 + gray-to-RGB, or you will have to test 3x as many bytes to check if a 1.1350 + pixel is transparent. You would also need to make sure that the 1.1351 + transparency information is upgraded to RGB. 1.1352 + 1.1353 + To summarize, the current flow is: 1.1354 + - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 1.1355 + with background "in place" if transparent, 1.1356 + convert to RGB if necessary 1.1357 + - Gray + alpha -> composite with gray background and remove alpha bytes, 1.1358 + convert to RGB if necessary 1.1359 + 1.1360 + To support RGB backgrounds for gray images we need: 1.1361 + - Gray + simple transparency -> convert to RGB + simple transparency, compare 1.1362 + 3 or 6 bytes and composite with background 1.1363 + "in place" if transparent (3x compare/pixel 1.1364 + compared to doing composite with gray bkgrnd) 1.1365 + - Gray + alpha -> convert to RGB + alpha, composite with background and 1.1366 + remove alpha bytes (3x float operations/pixel 1.1367 + compared with composite on gray background) 1.1368 + 1.1369 + Greg's change will do this. The reason it wasn't done before is for 1.1370 + performance, as this increases the per-pixel operations. If we would check 1.1371 + in advance if the background was gray or RGB, and position the gray-to-RGB 1.1372 + transform appropriately, then it would save a lot of work/time. 1.1373 + */ 1.1374 + 1.1375 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.1376 + /* if gray -> RGB, do so now only if background is non-gray; else do later 1.1377 + * for performance reasons */ 1.1378 + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1.1379 + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1.1380 + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1381 +#endif 1.1382 + 1.1383 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1384 + if ((png_ptr->transformations & PNG_BACKGROUND) && 1.1385 + ((png_ptr->num_trans != 0 ) || 1.1386 + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) 1.1387 + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1388 + &(png_ptr->trans_values), &(png_ptr->background) 1.1389 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.1390 + , &(png_ptr->background_1), 1.1391 + png_ptr->gamma_table, png_ptr->gamma_from_1, 1.1392 + png_ptr->gamma_to_1, png_ptr->gamma_16_table, 1.1393 + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, 1.1394 + png_ptr->gamma_shift 1.1395 +#endif 1.1396 +); 1.1397 +#endif 1.1398 + 1.1399 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.1400 + if ((png_ptr->transformations & PNG_GAMMA) && 1.1401 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.1402 + !((png_ptr->transformations & PNG_BACKGROUND) && 1.1403 + ((png_ptr->num_trans != 0) || 1.1404 + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && 1.1405 +#endif 1.1406 + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 1.1407 + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1408 + png_ptr->gamma_table, png_ptr->gamma_16_table, 1.1409 + png_ptr->gamma_shift); 1.1410 +#endif 1.1411 + 1.1412 +#if defined(PNG_READ_16_TO_8_SUPPORTED) 1.1413 + if (png_ptr->transformations & PNG_16_TO_8) 1.1414 + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1415 +#endif 1.1416 + 1.1417 +#if defined(PNG_READ_DITHER_SUPPORTED) 1.1418 + if (png_ptr->transformations & PNG_DITHER) 1.1419 + { 1.1420 + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1421 + png_ptr->palette_lookup, png_ptr->dither_index); 1.1422 + if (png_ptr->row_info.rowbytes == (png_uint_32)0) 1.1423 + png_error(png_ptr, "png_do_dither returned rowbytes=0"); 1.1424 + } 1.1425 +#endif 1.1426 + 1.1427 +#if defined(PNG_READ_INVERT_SUPPORTED) 1.1428 + if (png_ptr->transformations & PNG_INVERT_MONO) 1.1429 + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1430 +#endif 1.1431 + 1.1432 +#if defined(PNG_READ_SHIFT_SUPPORTED) 1.1433 + if (png_ptr->transformations & PNG_SHIFT) 1.1434 + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1435 + &(png_ptr->shift)); 1.1436 +#endif 1.1437 + 1.1438 +#if defined(PNG_READ_PACK_SUPPORTED) 1.1439 + if (png_ptr->transformations & PNG_PACK) 1.1440 + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1441 +#endif 1.1442 + 1.1443 +#if defined(PNG_READ_BGR_SUPPORTED) 1.1444 + if (png_ptr->transformations & PNG_BGR) 1.1445 + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1446 +#endif 1.1447 + 1.1448 +#if defined(PNG_READ_PACKSWAP_SUPPORTED) 1.1449 + if (png_ptr->transformations & PNG_PACKSWAP) 1.1450 + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1451 +#endif 1.1452 + 1.1453 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.1454 + /* if gray -> RGB, do so now only if we did not do so above */ 1.1455 + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1.1456 + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1.1457 + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1458 +#endif 1.1459 + 1.1460 +#if defined(PNG_READ_FILLER_SUPPORTED) 1.1461 + if (png_ptr->transformations & PNG_FILLER) 1.1462 + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 1.1463 + (png_uint_32)png_ptr->filler, png_ptr->flags); 1.1464 +#endif 1.1465 + 1.1466 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 1.1467 + if (png_ptr->transformations & PNG_INVERT_ALPHA) 1.1468 + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1469 +#endif 1.1470 + 1.1471 +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) 1.1472 + if (png_ptr->transformations & PNG_SWAP_ALPHA) 1.1473 + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1474 +#endif 1.1475 + 1.1476 +#if defined(PNG_READ_SWAP_SUPPORTED) 1.1477 + if (png_ptr->transformations & PNG_SWAP_BYTES) 1.1478 + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.1479 +#endif 1.1480 + 1.1481 +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 1.1482 + if (png_ptr->transformations & PNG_USER_TRANSFORM) 1.1483 + { 1.1484 + if (png_ptr->read_user_transform_fn != NULL) 1.1485 + (*(png_ptr->read_user_transform_fn)) /* user read transform function */ 1.1486 + (png_ptr, /* png_ptr */ 1.1487 + &(png_ptr->row_info), /* row_info: */ 1.1488 + /* png_uint_32 width; width of row */ 1.1489 + /* png_uint_32 rowbytes; number of bytes in row */ 1.1490 + /* png_byte color_type; color type of pixels */ 1.1491 + /* png_byte bit_depth; bit depth of samples */ 1.1492 + /* png_byte channels; number of channels (1-4) */ 1.1493 + /* png_byte pixel_depth; bits per pixel (depth*channels) */ 1.1494 + png_ptr->row_buf + 1); /* start of pixel data for row */ 1.1495 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) 1.1496 + if (png_ptr->user_transform_depth) 1.1497 + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; 1.1498 + if (png_ptr->user_transform_channels) 1.1499 + png_ptr->row_info.channels = png_ptr->user_transform_channels; 1.1500 +#endif 1.1501 + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * 1.1502 + png_ptr->row_info.channels); 1.1503 + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, 1.1504 + png_ptr->row_info.width); 1.1505 + } 1.1506 +#endif 1.1507 + 1.1508 +} 1.1509 + 1.1510 +#if defined(PNG_READ_PACK_SUPPORTED) 1.1511 +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 1.1512 + * without changing the actual values. Thus, if you had a row with 1.1513 + * a bit depth of 1, you would end up with bytes that only contained 1.1514 + * the numbers 0 or 1. If you would rather they contain 0 and 255, use 1.1515 + * png_do_shift() after this. 1.1516 + */ 1.1517 +void /* PRIVATE */ 1.1518 +png_do_unpack(png_row_infop row_info, png_bytep row) 1.1519 +{ 1.1520 + png_debug(1, "in png_do_unpack\n"); 1.1521 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1522 + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) 1.1523 +#else 1.1524 + if (row_info->bit_depth < 8) 1.1525 +#endif 1.1526 + { 1.1527 + png_uint_32 i; 1.1528 + png_uint_32 row_width=row_info->width; 1.1529 + 1.1530 + switch (row_info->bit_depth) 1.1531 + { 1.1532 + case 1: 1.1533 + { 1.1534 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 1.1535 + png_bytep dp = row + (png_size_t)row_width - 1; 1.1536 + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); 1.1537 + for (i = 0; i < row_width; i++) 1.1538 + { 1.1539 + *dp = (png_byte)((*sp >> shift) & 0x01); 1.1540 + if (shift == 7) 1.1541 + { 1.1542 + shift = 0; 1.1543 + sp--; 1.1544 + } 1.1545 + else 1.1546 + shift++; 1.1547 + 1.1548 + dp--; 1.1549 + } 1.1550 + break; 1.1551 + } 1.1552 + case 2: 1.1553 + { 1.1554 + 1.1555 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 1.1556 + png_bytep dp = row + (png_size_t)row_width - 1; 1.1557 + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.1558 + for (i = 0; i < row_width; i++) 1.1559 + { 1.1560 + *dp = (png_byte)((*sp >> shift) & 0x03); 1.1561 + if (shift == 6) 1.1562 + { 1.1563 + shift = 0; 1.1564 + sp--; 1.1565 + } 1.1566 + else 1.1567 + shift += 2; 1.1568 + 1.1569 + dp--; 1.1570 + } 1.1571 + break; 1.1572 + } 1.1573 + case 4: 1.1574 + { 1.1575 + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 1.1576 + png_bytep dp = row + (png_size_t)row_width - 1; 1.1577 + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 1.1578 + for (i = 0; i < row_width; i++) 1.1579 + { 1.1580 + *dp = (png_byte)((*sp >> shift) & 0x0f); 1.1581 + if (shift == 4) 1.1582 + { 1.1583 + shift = 0; 1.1584 + sp--; 1.1585 + } 1.1586 + else 1.1587 + shift = 4; 1.1588 + 1.1589 + dp--; 1.1590 + } 1.1591 + break; 1.1592 + } 1.1593 + } 1.1594 + row_info->bit_depth = 8; 1.1595 + row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1.1596 + row_info->rowbytes = row_width * row_info->channels; 1.1597 + } 1.1598 +} 1.1599 +#endif 1.1600 + 1.1601 +#if defined(PNG_READ_SHIFT_SUPPORTED) 1.1602 +/* Reverse the effects of png_do_shift. This routine merely shifts the 1.1603 + * pixels back to their significant bits values. Thus, if you have 1.1604 + * a row of bit depth 8, but only 5 are significant, this will shift 1.1605 + * the values back to 0 through 31. 1.1606 + */ 1.1607 +void /* PRIVATE */ 1.1608 +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) 1.1609 +{ 1.1610 + png_debug(1, "in png_do_unshift\n"); 1.1611 + if ( 1.1612 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1613 + row != NULL && row_info != NULL && sig_bits != NULL && 1.1614 +#endif 1.1615 + row_info->color_type != PNG_COLOR_TYPE_PALETTE) 1.1616 + { 1.1617 + int shift[4]; 1.1618 + int channels = 0; 1.1619 + int c; 1.1620 + png_uint_16 value = 0; 1.1621 + png_uint_32 row_width = row_info->width; 1.1622 + 1.1623 + if (row_info->color_type & PNG_COLOR_MASK_COLOR) 1.1624 + { 1.1625 + shift[channels++] = row_info->bit_depth - sig_bits->red; 1.1626 + shift[channels++] = row_info->bit_depth - sig_bits->green; 1.1627 + shift[channels++] = row_info->bit_depth - sig_bits->blue; 1.1628 + } 1.1629 + else 1.1630 + { 1.1631 + shift[channels++] = row_info->bit_depth - sig_bits->gray; 1.1632 + } 1.1633 + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 1.1634 + { 1.1635 + shift[channels++] = row_info->bit_depth - sig_bits->alpha; 1.1636 + } 1.1637 + 1.1638 + for (c = 0; c < channels; c++) 1.1639 + { 1.1640 + if (shift[c] <= 0) 1.1641 + shift[c] = 0; 1.1642 + else 1.1643 + value = 1; 1.1644 + } 1.1645 + 1.1646 + if (!value) 1.1647 + return; 1.1648 + 1.1649 + switch (row_info->bit_depth) 1.1650 + { 1.1651 + case 2: 1.1652 + { 1.1653 + png_bytep bp; 1.1654 + png_uint_32 i; 1.1655 + png_uint_32 istop = row_info->rowbytes; 1.1656 + 1.1657 + for (bp = row, i = 0; i < istop; i++) 1.1658 + { 1.1659 + *bp >>= 1; 1.1660 + *bp++ &= 0x55; 1.1661 + } 1.1662 + break; 1.1663 + } 1.1664 + case 4: 1.1665 + { 1.1666 + png_bytep bp = row; 1.1667 + png_uint_32 i; 1.1668 + png_uint_32 istop = row_info->rowbytes; 1.1669 + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | 1.1670 + (png_byte)((int)0xf >> shift[0])); 1.1671 + 1.1672 + for (i = 0; i < istop; i++) 1.1673 + { 1.1674 + *bp >>= shift[0]; 1.1675 + *bp++ &= mask; 1.1676 + } 1.1677 + break; 1.1678 + } 1.1679 + case 8: 1.1680 + { 1.1681 + png_bytep bp = row; 1.1682 + png_uint_32 i; 1.1683 + png_uint_32 istop = row_width * channels; 1.1684 + 1.1685 + for (i = 0; i < istop; i++) 1.1686 + { 1.1687 + *bp++ >>= shift[i%channels]; 1.1688 + } 1.1689 + break; 1.1690 + } 1.1691 + case 16: 1.1692 + { 1.1693 + png_bytep bp = row; 1.1694 + png_uint_32 i; 1.1695 + png_uint_32 istop = channels * row_width; 1.1696 + 1.1697 + for (i = 0; i < istop; i++) 1.1698 + { 1.1699 + value = (png_uint_16)((*bp << 8) + *(bp + 1)); 1.1700 + value >>= shift[i%channels]; 1.1701 + *bp++ = (png_byte)(value >> 8); 1.1702 + *bp++ = (png_byte)(value & 0xff); 1.1703 + } 1.1704 + break; 1.1705 + } 1.1706 + } 1.1707 + } 1.1708 +} 1.1709 +#endif 1.1710 + 1.1711 +#if defined(PNG_READ_16_TO_8_SUPPORTED) 1.1712 +/* chop rows of bit depth 16 down to 8 */ 1.1713 +void /* PRIVATE */ 1.1714 +png_do_chop(png_row_infop row_info, png_bytep row) 1.1715 +{ 1.1716 + png_debug(1, "in png_do_chop\n"); 1.1717 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1718 + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) 1.1719 +#else 1.1720 + if (row_info->bit_depth == 16) 1.1721 +#endif 1.1722 + { 1.1723 + png_bytep sp = row; 1.1724 + png_bytep dp = row; 1.1725 + png_uint_32 i; 1.1726 + png_uint_32 istop = row_info->width * row_info->channels; 1.1727 + 1.1728 + for (i = 0; i<istop; i++, sp += 2, dp++) 1.1729 + { 1.1730 +#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED) 1.1731 + /* This does a more accurate scaling of the 16-bit color 1.1732 + * value, rather than a simple low-byte truncation. 1.1733 + * 1.1734 + * What the ideal calculation should be: 1.1735 + * *dp = (((((png_uint_32)(*sp) << 8) | 1.1736 + * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L; 1.1737 + * 1.1738 + * GRR: no, I think this is what it really should be: 1.1739 + * *dp = (((((png_uint_32)(*sp) << 8) | 1.1740 + * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L; 1.1741 + * 1.1742 + * GRR: here's the exact calculation with shifts: 1.1743 + * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L; 1.1744 + * *dp = (temp - (temp >> 8)) >> 8; 1.1745 + * 1.1746 + * Approximate calculation with shift/add instead of multiply/divide: 1.1747 + * *dp = ((((png_uint_32)(*sp) << 8) | 1.1748 + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; 1.1749 + * 1.1750 + * What we actually do to avoid extra shifting and conversion: 1.1751 + */ 1.1752 + 1.1753 + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); 1.1754 +#else 1.1755 + /* Simply discard the low order byte */ 1.1756 + *dp = *sp; 1.1757 +#endif 1.1758 + } 1.1759 + row_info->bit_depth = 8; 1.1760 + row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1.1761 + row_info->rowbytes = row_info->width * row_info->channels; 1.1762 + } 1.1763 +} 1.1764 +#endif 1.1765 + 1.1766 +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) 1.1767 +void /* PRIVATE */ 1.1768 +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 1.1769 +{ 1.1770 + png_debug(1, "in png_do_read_swap_alpha\n"); 1.1771 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1772 + if (row != NULL && row_info != NULL) 1.1773 +#endif 1.1774 + { 1.1775 + png_uint_32 row_width = row_info->width; 1.1776 + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.1777 + { 1.1778 + /* This converts from RGBA to ARGB */ 1.1779 + if (row_info->bit_depth == 8) 1.1780 + { 1.1781 + png_bytep sp = row + row_info->rowbytes; 1.1782 + png_bytep dp = sp; 1.1783 + png_byte save; 1.1784 + png_uint_32 i; 1.1785 + 1.1786 + for (i = 0; i < row_width; i++) 1.1787 + { 1.1788 + save = *(--sp); 1.1789 + *(--dp) = *(--sp); 1.1790 + *(--dp) = *(--sp); 1.1791 + *(--dp) = *(--sp); 1.1792 + *(--dp) = save; 1.1793 + } 1.1794 + } 1.1795 + /* This converts from RRGGBBAA to AARRGGBB */ 1.1796 + else 1.1797 + { 1.1798 + png_bytep sp = row + row_info->rowbytes; 1.1799 + png_bytep dp = sp; 1.1800 + png_byte save[2]; 1.1801 + png_uint_32 i; 1.1802 + 1.1803 + for (i = 0; i < row_width; i++) 1.1804 + { 1.1805 + save[0] = *(--sp); 1.1806 + save[1] = *(--sp); 1.1807 + *(--dp) = *(--sp); 1.1808 + *(--dp) = *(--sp); 1.1809 + *(--dp) = *(--sp); 1.1810 + *(--dp) = *(--sp); 1.1811 + *(--dp) = *(--sp); 1.1812 + *(--dp) = *(--sp); 1.1813 + *(--dp) = save[0]; 1.1814 + *(--dp) = save[1]; 1.1815 + } 1.1816 + } 1.1817 + } 1.1818 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.1819 + { 1.1820 + /* This converts from GA to AG */ 1.1821 + if (row_info->bit_depth == 8) 1.1822 + { 1.1823 + png_bytep sp = row + row_info->rowbytes; 1.1824 + png_bytep dp = sp; 1.1825 + png_byte save; 1.1826 + png_uint_32 i; 1.1827 + 1.1828 + for (i = 0; i < row_width; i++) 1.1829 + { 1.1830 + save = *(--sp); 1.1831 + *(--dp) = *(--sp); 1.1832 + *(--dp) = save; 1.1833 + } 1.1834 + } 1.1835 + /* This converts from GGAA to AAGG */ 1.1836 + else 1.1837 + { 1.1838 + png_bytep sp = row + row_info->rowbytes; 1.1839 + png_bytep dp = sp; 1.1840 + png_byte save[2]; 1.1841 + png_uint_32 i; 1.1842 + 1.1843 + for (i = 0; i < row_width; i++) 1.1844 + { 1.1845 + save[0] = *(--sp); 1.1846 + save[1] = *(--sp); 1.1847 + *(--dp) = *(--sp); 1.1848 + *(--dp) = *(--sp); 1.1849 + *(--dp) = save[0]; 1.1850 + *(--dp) = save[1]; 1.1851 + } 1.1852 + } 1.1853 + } 1.1854 + } 1.1855 +} 1.1856 +#endif 1.1857 + 1.1858 +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) 1.1859 +void /* PRIVATE */ 1.1860 +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 1.1861 +{ 1.1862 + png_debug(1, "in png_do_read_invert_alpha\n"); 1.1863 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1864 + if (row != NULL && row_info != NULL) 1.1865 +#endif 1.1866 + { 1.1867 + png_uint_32 row_width = row_info->width; 1.1868 + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.1869 + { 1.1870 + /* This inverts the alpha channel in RGBA */ 1.1871 + if (row_info->bit_depth == 8) 1.1872 + { 1.1873 + png_bytep sp = row + row_info->rowbytes; 1.1874 + png_bytep dp = sp; 1.1875 + png_uint_32 i; 1.1876 + 1.1877 + for (i = 0; i < row_width; i++) 1.1878 + { 1.1879 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1880 + 1.1881 +/* This does nothing: 1.1882 + *(--dp) = *(--sp); 1.1883 + *(--dp) = *(--sp); 1.1884 + *(--dp) = *(--sp); 1.1885 + We can replace it with: 1.1886 +*/ 1.1887 + sp-=3; 1.1888 + dp=sp; 1.1889 + } 1.1890 + } 1.1891 + /* This inverts the alpha channel in RRGGBBAA */ 1.1892 + else 1.1893 + { 1.1894 + png_bytep sp = row + row_info->rowbytes; 1.1895 + png_bytep dp = sp; 1.1896 + png_uint_32 i; 1.1897 + 1.1898 + for (i = 0; i < row_width; i++) 1.1899 + { 1.1900 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1901 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1902 + 1.1903 +/* This does nothing: 1.1904 + *(--dp) = *(--sp); 1.1905 + *(--dp) = *(--sp); 1.1906 + *(--dp) = *(--sp); 1.1907 + *(--dp) = *(--sp); 1.1908 + *(--dp) = *(--sp); 1.1909 + *(--dp) = *(--sp); 1.1910 + We can replace it with: 1.1911 +*/ 1.1912 + sp-=6; 1.1913 + dp=sp; 1.1914 + } 1.1915 + } 1.1916 + } 1.1917 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.1918 + { 1.1919 + /* This inverts the alpha channel in GA */ 1.1920 + if (row_info->bit_depth == 8) 1.1921 + { 1.1922 + png_bytep sp = row + row_info->rowbytes; 1.1923 + png_bytep dp = sp; 1.1924 + png_uint_32 i; 1.1925 + 1.1926 + for (i = 0; i < row_width; i++) 1.1927 + { 1.1928 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1929 + *(--dp) = *(--sp); 1.1930 + } 1.1931 + } 1.1932 + /* This inverts the alpha channel in GGAA */ 1.1933 + else 1.1934 + { 1.1935 + png_bytep sp = row + row_info->rowbytes; 1.1936 + png_bytep dp = sp; 1.1937 + png_uint_32 i; 1.1938 + 1.1939 + for (i = 0; i < row_width; i++) 1.1940 + { 1.1941 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1942 + *(--dp) = (png_byte)(255 - *(--sp)); 1.1943 +/* 1.1944 + *(--dp) = *(--sp); 1.1945 + *(--dp) = *(--sp); 1.1946 +*/ 1.1947 + sp-=2; 1.1948 + dp=sp; 1.1949 + } 1.1950 + } 1.1951 + } 1.1952 + } 1.1953 +} 1.1954 +#endif 1.1955 + 1.1956 +#if defined(PNG_READ_FILLER_SUPPORTED) 1.1957 +/* Add filler channel if we have RGB color */ 1.1958 +void /* PRIVATE */ 1.1959 +png_do_read_filler(png_row_infop row_info, png_bytep row, 1.1960 + png_uint_32 filler, png_uint_32 flags) 1.1961 +{ 1.1962 + png_uint_32 i; 1.1963 + png_uint_32 row_width = row_info->width; 1.1964 + 1.1965 + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); 1.1966 + png_byte lo_filler = (png_byte)(filler & 0xff); 1.1967 + 1.1968 + png_debug(1, "in png_do_read_filler\n"); 1.1969 + if ( 1.1970 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.1971 + row != NULL && row_info != NULL && 1.1972 +#endif 1.1973 + row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.1974 + { 1.1975 + if (row_info->bit_depth == 8) 1.1976 + { 1.1977 + /* This changes the data from G to GX */ 1.1978 + if (flags & PNG_FLAG_FILLER_AFTER) 1.1979 + { 1.1980 + png_bytep sp = row + (png_size_t)row_width; 1.1981 + png_bytep dp = sp + (png_size_t)row_width; 1.1982 + for (i = 1; i < row_width; i++) 1.1983 + { 1.1984 + *(--dp) = lo_filler; 1.1985 + *(--dp) = *(--sp); 1.1986 + } 1.1987 + *(--dp) = lo_filler; 1.1988 + row_info->channels = 2; 1.1989 + row_info->pixel_depth = 16; 1.1990 + row_info->rowbytes = row_width * 2; 1.1991 + } 1.1992 + /* This changes the data from G to XG */ 1.1993 + else 1.1994 + { 1.1995 + png_bytep sp = row + (png_size_t)row_width; 1.1996 + png_bytep dp = sp + (png_size_t)row_width; 1.1997 + for (i = 0; i < row_width; i++) 1.1998 + { 1.1999 + *(--dp) = *(--sp); 1.2000 + *(--dp) = lo_filler; 1.2001 + } 1.2002 + row_info->channels = 2; 1.2003 + row_info->pixel_depth = 16; 1.2004 + row_info->rowbytes = row_width * 2; 1.2005 + } 1.2006 + } 1.2007 + else if (row_info->bit_depth == 16) 1.2008 + { 1.2009 + /* This changes the data from GG to GGXX */ 1.2010 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2011 + { 1.2012 + png_bytep sp = row + (png_size_t)row_width * 2; 1.2013 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2014 + for (i = 1; i < row_width; i++) 1.2015 + { 1.2016 + *(--dp) = hi_filler; 1.2017 + *(--dp) = lo_filler; 1.2018 + *(--dp) = *(--sp); 1.2019 + *(--dp) = *(--sp); 1.2020 + } 1.2021 + *(--dp) = hi_filler; 1.2022 + *(--dp) = lo_filler; 1.2023 + row_info->channels = 2; 1.2024 + row_info->pixel_depth = 32; 1.2025 + row_info->rowbytes = row_width * 4; 1.2026 + } 1.2027 + /* This changes the data from GG to XXGG */ 1.2028 + else 1.2029 + { 1.2030 + png_bytep sp = row + (png_size_t)row_width * 2; 1.2031 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2032 + for (i = 0; i < row_width; i++) 1.2033 + { 1.2034 + *(--dp) = *(--sp); 1.2035 + *(--dp) = *(--sp); 1.2036 + *(--dp) = hi_filler; 1.2037 + *(--dp) = lo_filler; 1.2038 + } 1.2039 + row_info->channels = 2; 1.2040 + row_info->pixel_depth = 32; 1.2041 + row_info->rowbytes = row_width * 4; 1.2042 + } 1.2043 + } 1.2044 + } /* COLOR_TYPE == GRAY */ 1.2045 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 1.2046 + { 1.2047 + if (row_info->bit_depth == 8) 1.2048 + { 1.2049 + /* This changes the data from RGB to RGBX */ 1.2050 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2051 + { 1.2052 + png_bytep sp = row + (png_size_t)row_width * 3; 1.2053 + png_bytep dp = sp + (png_size_t)row_width; 1.2054 + for (i = 1; i < row_width; i++) 1.2055 + { 1.2056 + *(--dp) = lo_filler; 1.2057 + *(--dp) = *(--sp); 1.2058 + *(--dp) = *(--sp); 1.2059 + *(--dp) = *(--sp); 1.2060 + } 1.2061 + *(--dp) = lo_filler; 1.2062 + row_info->channels = 4; 1.2063 + row_info->pixel_depth = 32; 1.2064 + row_info->rowbytes = row_width * 4; 1.2065 + } 1.2066 + /* This changes the data from RGB to XRGB */ 1.2067 + else 1.2068 + { 1.2069 + png_bytep sp = row + (png_size_t)row_width * 3; 1.2070 + png_bytep dp = sp + (png_size_t)row_width; 1.2071 + for (i = 0; i < row_width; i++) 1.2072 + { 1.2073 + *(--dp) = *(--sp); 1.2074 + *(--dp) = *(--sp); 1.2075 + *(--dp) = *(--sp); 1.2076 + *(--dp) = lo_filler; 1.2077 + } 1.2078 + row_info->channels = 4; 1.2079 + row_info->pixel_depth = 32; 1.2080 + row_info->rowbytes = row_width * 4; 1.2081 + } 1.2082 + } 1.2083 + else if (row_info->bit_depth == 16) 1.2084 + { 1.2085 + /* This changes the data from RRGGBB to RRGGBBXX */ 1.2086 + if (flags & PNG_FLAG_FILLER_AFTER) 1.2087 + { 1.2088 + png_bytep sp = row + (png_size_t)row_width * 6; 1.2089 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2090 + for (i = 1; i < row_width; i++) 1.2091 + { 1.2092 + *(--dp) = hi_filler; 1.2093 + *(--dp) = lo_filler; 1.2094 + *(--dp) = *(--sp); 1.2095 + *(--dp) = *(--sp); 1.2096 + *(--dp) = *(--sp); 1.2097 + *(--dp) = *(--sp); 1.2098 + *(--dp) = *(--sp); 1.2099 + *(--dp) = *(--sp); 1.2100 + } 1.2101 + *(--dp) = hi_filler; 1.2102 + *(--dp) = lo_filler; 1.2103 + row_info->channels = 4; 1.2104 + row_info->pixel_depth = 64; 1.2105 + row_info->rowbytes = row_width * 8; 1.2106 + } 1.2107 + /* This changes the data from RRGGBB to XXRRGGBB */ 1.2108 + else 1.2109 + { 1.2110 + png_bytep sp = row + (png_size_t)row_width * 6; 1.2111 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2112 + for (i = 0; i < row_width; i++) 1.2113 + { 1.2114 + *(--dp) = *(--sp); 1.2115 + *(--dp) = *(--sp); 1.2116 + *(--dp) = *(--sp); 1.2117 + *(--dp) = *(--sp); 1.2118 + *(--dp) = *(--sp); 1.2119 + *(--dp) = *(--sp); 1.2120 + *(--dp) = hi_filler; 1.2121 + *(--dp) = lo_filler; 1.2122 + } 1.2123 + row_info->channels = 4; 1.2124 + row_info->pixel_depth = 64; 1.2125 + row_info->rowbytes = row_width * 8; 1.2126 + } 1.2127 + } 1.2128 + } /* COLOR_TYPE == RGB */ 1.2129 +} 1.2130 +#endif 1.2131 + 1.2132 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 1.2133 +/* expand grayscale files to RGB, with or without alpha */ 1.2134 +void /* PRIVATE */ 1.2135 +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 1.2136 +{ 1.2137 + png_uint_32 i; 1.2138 + png_uint_32 row_width = row_info->width; 1.2139 + 1.2140 + png_debug(1, "in png_do_gray_to_rgb\n"); 1.2141 + if (row_info->bit_depth >= 8 && 1.2142 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.2143 + row != NULL && row_info != NULL && 1.2144 +#endif 1.2145 + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) 1.2146 + { 1.2147 + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.2148 + { 1.2149 + if (row_info->bit_depth == 8) 1.2150 + { 1.2151 + png_bytep sp = row + (png_size_t)row_width - 1; 1.2152 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2153 + for (i = 0; i < row_width; i++) 1.2154 + { 1.2155 + *(dp--) = *sp; 1.2156 + *(dp--) = *sp; 1.2157 + *(dp--) = *(sp--); 1.2158 + } 1.2159 + } 1.2160 + else 1.2161 + { 1.2162 + png_bytep sp = row + (png_size_t)row_width * 2 - 1; 1.2163 + png_bytep dp = sp + (png_size_t)row_width * 4; 1.2164 + for (i = 0; i < row_width; i++) 1.2165 + { 1.2166 + *(dp--) = *sp; 1.2167 + *(dp--) = *(sp - 1); 1.2168 + *(dp--) = *sp; 1.2169 + *(dp--) = *(sp - 1); 1.2170 + *(dp--) = *(sp--); 1.2171 + *(dp--) = *(sp--); 1.2172 + } 1.2173 + } 1.2174 + } 1.2175 + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1.2176 + { 1.2177 + if (row_info->bit_depth == 8) 1.2178 + { 1.2179 + png_bytep sp = row + (png_size_t)row_width * 2 - 1; 1.2180 + png_bytep dp = sp + (png_size_t)row_width * 2; 1.2181 + for (i = 0; i < row_width; i++) 1.2182 + { 1.2183 + *(dp--) = *(sp--); 1.2184 + *(dp--) = *sp; 1.2185 + *(dp--) = *sp; 1.2186 + *(dp--) = *(sp--); 1.2187 + } 1.2188 + } 1.2189 + else 1.2190 + { 1.2191 + png_bytep sp = row + (png_size_t)row_width * 4 - 1; 1.2192 + png_bytep dp = sp + (png_size_t)row_width * 4; 1.2193 + for (i = 0; i < row_width; i++) 1.2194 + { 1.2195 + *(dp--) = *(sp--); 1.2196 + *(dp--) = *(sp--); 1.2197 + *(dp--) = *sp; 1.2198 + *(dp--) = *(sp - 1); 1.2199 + *(dp--) = *sp; 1.2200 + *(dp--) = *(sp - 1); 1.2201 + *(dp--) = *(sp--); 1.2202 + *(dp--) = *(sp--); 1.2203 + } 1.2204 + } 1.2205 + } 1.2206 + row_info->channels += (png_byte)2; 1.2207 + row_info->color_type |= PNG_COLOR_MASK_COLOR; 1.2208 + row_info->pixel_depth = (png_byte)(row_info->channels * 1.2209 + row_info->bit_depth); 1.2210 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.2211 + } 1.2212 +} 1.2213 +#endif 1.2214 + 1.2215 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.2216 +/* reduce RGB files to grayscale, with or without alpha 1.2217 + * using the equation given in Poynton's ColorFAQ at 1.2218 + * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008) 1.2219 + * New link: 1.2220 + * <http://www.poynton.com/notes/colour_and_gamma/> 1.2221 + * Charles Poynton poynton at poynton.com 1.2222 + * 1.2223 + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 1.2224 + * 1.2225 + * We approximate this with 1.2226 + * 1.2227 + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B 1.2228 + * 1.2229 + * which can be expressed with integers as 1.2230 + * 1.2231 + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 1.2232 + * 1.2233 + * The calculation is to be done in a linear colorspace. 1.2234 + * 1.2235 + * Other integer coefficents can be used via png_set_rgb_to_gray(). 1.2236 + */ 1.2237 +int /* PRIVATE */ 1.2238 +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) 1.2239 + 1.2240 +{ 1.2241 + png_uint_32 i; 1.2242 + 1.2243 + png_uint_32 row_width = row_info->width; 1.2244 + int rgb_error = 0; 1.2245 + 1.2246 + png_debug(1, "in png_do_rgb_to_gray\n"); 1.2247 + if ( 1.2248 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.2249 + row != NULL && row_info != NULL && 1.2250 +#endif 1.2251 + (row_info->color_type & PNG_COLOR_MASK_COLOR)) 1.2252 + { 1.2253 + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 1.2254 + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 1.2255 + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; 1.2256 + 1.2257 + if (row_info->color_type == PNG_COLOR_TYPE_RGB) 1.2258 + { 1.2259 + if (row_info->bit_depth == 8) 1.2260 + { 1.2261 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2262 + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 1.2263 + { 1.2264 + png_bytep sp = row; 1.2265 + png_bytep dp = row; 1.2266 + 1.2267 + for (i = 0; i < row_width; i++) 1.2268 + { 1.2269 + png_byte red = png_ptr->gamma_to_1[*(sp++)]; 1.2270 + png_byte green = png_ptr->gamma_to_1[*(sp++)]; 1.2271 + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 1.2272 + if (red != green || red != blue) 1.2273 + { 1.2274 + rgb_error |= 1; 1.2275 + *(dp++) = png_ptr->gamma_from_1[ 1.2276 + (rc*red + gc*green + bc*blue)>>15]; 1.2277 + } 1.2278 + else 1.2279 + *(dp++) = *(sp - 1); 1.2280 + } 1.2281 + } 1.2282 + else 1.2283 +#endif 1.2284 + { 1.2285 + png_bytep sp = row; 1.2286 + png_bytep dp = row; 1.2287 + for (i = 0; i < row_width; i++) 1.2288 + { 1.2289 + png_byte red = *(sp++); 1.2290 + png_byte green = *(sp++); 1.2291 + png_byte blue = *(sp++); 1.2292 + if (red != green || red != blue) 1.2293 + { 1.2294 + rgb_error |= 1; 1.2295 + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 1.2296 + } 1.2297 + else 1.2298 + *(dp++) = *(sp - 1); 1.2299 + } 1.2300 + } 1.2301 + } 1.2302 + 1.2303 + else /* RGB bit_depth == 16 */ 1.2304 + { 1.2305 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2306 + if (png_ptr->gamma_16_to_1 != NULL && 1.2307 + png_ptr->gamma_16_from_1 != NULL) 1.2308 + { 1.2309 + png_bytep sp = row; 1.2310 + png_bytep dp = row; 1.2311 + for (i = 0; i < row_width; i++) 1.2312 + { 1.2313 + png_uint_16 red, green, blue, w; 1.2314 + 1.2315 + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2316 + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2317 + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2318 + 1.2319 + if (red == green && red == blue) 1.2320 + w = red; 1.2321 + else 1.2322 + { 1.2323 + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 1.2324 + png_ptr->gamma_shift][red>>8]; 1.2325 + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> 1.2326 + png_ptr->gamma_shift][green>>8]; 1.2327 + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 1.2328 + png_ptr->gamma_shift][blue>>8]; 1.2329 + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 1.2330 + + bc*blue_1)>>15); 1.2331 + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 1.2332 + png_ptr->gamma_shift][gray16 >> 8]; 1.2333 + rgb_error |= 1; 1.2334 + } 1.2335 + 1.2336 + *(dp++) = (png_byte)((w>>8) & 0xff); 1.2337 + *(dp++) = (png_byte)(w & 0xff); 1.2338 + } 1.2339 + } 1.2340 + else 1.2341 +#endif 1.2342 + { 1.2343 + png_bytep sp = row; 1.2344 + png_bytep dp = row; 1.2345 + for (i = 0; i < row_width; i++) 1.2346 + { 1.2347 + png_uint_16 red, green, blue, gray16; 1.2348 + 1.2349 + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2350 + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2351 + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2352 + 1.2353 + if (red != green || red != blue) 1.2354 + rgb_error |= 1; 1.2355 + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 1.2356 + *(dp++) = (png_byte)((gray16>>8) & 0xff); 1.2357 + *(dp++) = (png_byte)(gray16 & 0xff); 1.2358 + } 1.2359 + } 1.2360 + } 1.2361 + } 1.2362 + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.2363 + { 1.2364 + if (row_info->bit_depth == 8) 1.2365 + { 1.2366 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2367 + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 1.2368 + { 1.2369 + png_bytep sp = row; 1.2370 + png_bytep dp = row; 1.2371 + for (i = 0; i < row_width; i++) 1.2372 + { 1.2373 + png_byte red = png_ptr->gamma_to_1[*(sp++)]; 1.2374 + png_byte green = png_ptr->gamma_to_1[*(sp++)]; 1.2375 + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 1.2376 + if (red != green || red != blue) 1.2377 + rgb_error |= 1; 1.2378 + *(dp++) = png_ptr->gamma_from_1 1.2379 + [(rc*red + gc*green + bc*blue)>>15]; 1.2380 + *(dp++) = *(sp++); /* alpha */ 1.2381 + } 1.2382 + } 1.2383 + else 1.2384 +#endif 1.2385 + { 1.2386 + png_bytep sp = row; 1.2387 + png_bytep dp = row; 1.2388 + for (i = 0; i < row_width; i++) 1.2389 + { 1.2390 + png_byte red = *(sp++); 1.2391 + png_byte green = *(sp++); 1.2392 + png_byte blue = *(sp++); 1.2393 + if (red != green || red != blue) 1.2394 + rgb_error |= 1; 1.2395 + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 1.2396 + *(dp++) = *(sp++); /* alpha */ 1.2397 + } 1.2398 + } 1.2399 + } 1.2400 + else /* RGBA bit_depth == 16 */ 1.2401 + { 1.2402 +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2403 + if (png_ptr->gamma_16_to_1 != NULL && 1.2404 + png_ptr->gamma_16_from_1 != NULL) 1.2405 + { 1.2406 + png_bytep sp = row; 1.2407 + png_bytep dp = row; 1.2408 + for (i = 0; i < row_width; i++) 1.2409 + { 1.2410 + png_uint_16 red, green, blue, w; 1.2411 + 1.2412 + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2413 + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2414 + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 1.2415 + 1.2416 + if (red == green && red == blue) 1.2417 + w = red; 1.2418 + else 1.2419 + { 1.2420 + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 1.2421 + png_ptr->gamma_shift][red>>8]; 1.2422 + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> 1.2423 + png_ptr->gamma_shift][green>>8]; 1.2424 + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 1.2425 + png_ptr->gamma_shift][blue>>8]; 1.2426 + png_uint_16 gray16 = (png_uint_16)((rc * red_1 1.2427 + + gc * green_1 + bc * blue_1)>>15); 1.2428 + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 1.2429 + png_ptr->gamma_shift][gray16 >> 8]; 1.2430 + rgb_error |= 1; 1.2431 + } 1.2432 + 1.2433 + *(dp++) = (png_byte)((w>>8) & 0xff); 1.2434 + *(dp++) = (png_byte)(w & 0xff); 1.2435 + *(dp++) = *(sp++); /* alpha */ 1.2436 + *(dp++) = *(sp++); 1.2437 + } 1.2438 + } 1.2439 + else 1.2440 +#endif 1.2441 + { 1.2442 + png_bytep sp = row; 1.2443 + png_bytep dp = row; 1.2444 + for (i = 0; i < row_width; i++) 1.2445 + { 1.2446 + png_uint_16 red, green, blue, gray16; 1.2447 + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 1.2448 + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 1.2449 + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 1.2450 + if (red != green || red != blue) 1.2451 + rgb_error |= 1; 1.2452 + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 1.2453 + *(dp++) = (png_byte)((gray16>>8) & 0xff); 1.2454 + *(dp++) = (png_byte)(gray16 & 0xff); 1.2455 + *(dp++) = *(sp++); /* alpha */ 1.2456 + *(dp++) = *(sp++); 1.2457 + } 1.2458 + } 1.2459 + } 1.2460 + } 1.2461 + row_info->channels -= (png_byte)2; 1.2462 + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; 1.2463 + row_info->pixel_depth = (png_byte)(row_info->channels * 1.2464 + row_info->bit_depth); 1.2465 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.2466 + } 1.2467 + return rgb_error; 1.2468 +} 1.2469 +#endif 1.2470 + 1.2471 +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth 1.2472 + * large of png_color. This lets grayscale images be treated as 1.2473 + * paletted. Most useful for gamma correction and simplification 1.2474 + * of code. 1.2475 + */ 1.2476 +void PNGAPI 1.2477 +png_build_grayscale_palette(int bit_depth, png_colorp palette) 1.2478 +{ 1.2479 + int num_palette; 1.2480 + int color_inc; 1.2481 + int i; 1.2482 + int v; 1.2483 + 1.2484 + png_debug(1, "in png_do_build_grayscale_palette\n"); 1.2485 + if (palette == NULL) 1.2486 + return; 1.2487 + 1.2488 + switch (bit_depth) 1.2489 + { 1.2490 + case 1: 1.2491 + num_palette = 2; 1.2492 + color_inc = 0xff; 1.2493 + break; 1.2494 + case 2: 1.2495 + num_palette = 4; 1.2496 + color_inc = 0x55; 1.2497 + break; 1.2498 + case 4: 1.2499 + num_palette = 16; 1.2500 + color_inc = 0x11; 1.2501 + break; 1.2502 + case 8: 1.2503 + num_palette = 256; 1.2504 + color_inc = 1; 1.2505 + break; 1.2506 + default: 1.2507 + num_palette = 0; 1.2508 + color_inc = 0; 1.2509 + break; 1.2510 + } 1.2511 + 1.2512 + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) 1.2513 + { 1.2514 + palette[i].red = (png_byte)v; 1.2515 + palette[i].green = (png_byte)v; 1.2516 + palette[i].blue = (png_byte)v; 1.2517 + } 1.2518 +} 1.2519 + 1.2520 +/* This function is currently unused. Do we really need it? */ 1.2521 +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) 1.2522 +void /* PRIVATE */ 1.2523 +png_correct_palette(png_structp png_ptr, png_colorp palette, 1.2524 + int num_palette) 1.2525 +{ 1.2526 + png_debug(1, "in png_correct_palette\n"); 1.2527 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 1.2528 + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 1.2529 + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) 1.2530 + { 1.2531 + png_color back, back_1; 1.2532 + 1.2533 + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 1.2534 + { 1.2535 + back.red = png_ptr->gamma_table[png_ptr->background.red]; 1.2536 + back.green = png_ptr->gamma_table[png_ptr->background.green]; 1.2537 + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 1.2538 + 1.2539 + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 1.2540 + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 1.2541 + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 1.2542 + } 1.2543 + else 1.2544 + { 1.2545 + double g; 1.2546 + 1.2547 + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); 1.2548 + 1.2549 + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || 1.2550 + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) 1.2551 + { 1.2552 + back.red = png_ptr->background.red; 1.2553 + back.green = png_ptr->background.green; 1.2554 + back.blue = png_ptr->background.blue; 1.2555 + } 1.2556 + else 1.2557 + { 1.2558 + back.red = 1.2559 + (png_byte)(pow((double)png_ptr->background.red/255, g) * 1.2560 + 255.0 + 0.5); 1.2561 + back.green = 1.2562 + (png_byte)(pow((double)png_ptr->background.green/255, g) * 1.2563 + 255.0 + 0.5); 1.2564 + back.blue = 1.2565 + (png_byte)(pow((double)png_ptr->background.blue/255, g) * 1.2566 + 255.0 + 0.5); 1.2567 + } 1.2568 + 1.2569 + g = 1.0 / png_ptr->background_gamma; 1.2570 + 1.2571 + back_1.red = 1.2572 + (png_byte)(pow((double)png_ptr->background.red/255, g) * 1.2573 + 255.0 + 0.5); 1.2574 + back_1.green = 1.2575 + (png_byte)(pow((double)png_ptr->background.green/255, g) * 1.2576 + 255.0 + 0.5); 1.2577 + back_1.blue = 1.2578 + (png_byte)(pow((double)png_ptr->background.blue/255, g) * 1.2579 + 255.0 + 0.5); 1.2580 + } 1.2581 + 1.2582 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.2583 + { 1.2584 + png_uint_32 i; 1.2585 + 1.2586 + for (i = 0; i < (png_uint_32)num_palette; i++) 1.2587 + { 1.2588 + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) 1.2589 + { 1.2590 + palette[i] = back; 1.2591 + } 1.2592 + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) 1.2593 + { 1.2594 + png_byte v, w; 1.2595 + 1.2596 + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; 1.2597 + png_composite(w, v, png_ptr->trans[i], back_1.red); 1.2598 + palette[i].red = png_ptr->gamma_from_1[w]; 1.2599 + 1.2600 + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; 1.2601 + png_composite(w, v, png_ptr->trans[i], back_1.green); 1.2602 + palette[i].green = png_ptr->gamma_from_1[w]; 1.2603 + 1.2604 + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; 1.2605 + png_composite(w, v, png_ptr->trans[i], back_1.blue); 1.2606 + palette[i].blue = png_ptr->gamma_from_1[w]; 1.2607 + } 1.2608 + else 1.2609 + { 1.2610 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.2611 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.2612 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.2613 + } 1.2614 + } 1.2615 + } 1.2616 + else 1.2617 + { 1.2618 + int i; 1.2619 + 1.2620 + for (i = 0; i < num_palette; i++) 1.2621 + { 1.2622 + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) 1.2623 + { 1.2624 + palette[i] = back; 1.2625 + } 1.2626 + else 1.2627 + { 1.2628 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.2629 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.2630 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.2631 + } 1.2632 + } 1.2633 + } 1.2634 + } 1.2635 + else 1.2636 +#endif 1.2637 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2638 + if (png_ptr->transformations & PNG_GAMMA) 1.2639 + { 1.2640 + int i; 1.2641 + 1.2642 + for (i = 0; i < num_palette; i++) 1.2643 + { 1.2644 + palette[i].red = png_ptr->gamma_table[palette[i].red]; 1.2645 + palette[i].green = png_ptr->gamma_table[palette[i].green]; 1.2646 + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1.2647 + } 1.2648 + } 1.2649 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2650 + else 1.2651 +#endif 1.2652 +#endif 1.2653 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2654 + if (png_ptr->transformations & PNG_BACKGROUND) 1.2655 + { 1.2656 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.2657 + { 1.2658 + png_color back; 1.2659 + 1.2660 + back.red = (png_byte)png_ptr->background.red; 1.2661 + back.green = (png_byte)png_ptr->background.green; 1.2662 + back.blue = (png_byte)png_ptr->background.blue; 1.2663 + 1.2664 + for (i = 0; i < (int)png_ptr->num_trans; i++) 1.2665 + { 1.2666 + if (png_ptr->trans[i] == 0) 1.2667 + { 1.2668 + palette[i].red = back.red; 1.2669 + palette[i].green = back.green; 1.2670 + palette[i].blue = back.blue; 1.2671 + } 1.2672 + else if (png_ptr->trans[i] != 0xff) 1.2673 + { 1.2674 + png_composite(palette[i].red, png_ptr->palette[i].red, 1.2675 + png_ptr->trans[i], back.red); 1.2676 + png_composite(palette[i].green, png_ptr->palette[i].green, 1.2677 + png_ptr->trans[i], back.green); 1.2678 + png_composite(palette[i].blue, png_ptr->palette[i].blue, 1.2679 + png_ptr->trans[i], back.blue); 1.2680 + } 1.2681 + } 1.2682 + } 1.2683 + else /* assume grayscale palette (what else could it be?) */ 1.2684 + { 1.2685 + int i; 1.2686 + 1.2687 + for (i = 0; i < num_palette; i++) 1.2688 + { 1.2689 + if (i == (png_byte)png_ptr->trans_values.gray) 1.2690 + { 1.2691 + palette[i].red = (png_byte)png_ptr->background.red; 1.2692 + palette[i].green = (png_byte)png_ptr->background.green; 1.2693 + palette[i].blue = (png_byte)png_ptr->background.blue; 1.2694 + } 1.2695 + } 1.2696 + } 1.2697 + } 1.2698 +#endif 1.2699 +} 1.2700 +#endif 1.2701 + 1.2702 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) 1.2703 +/* Replace any alpha or transparency with the supplied background color. 1.2704 + * "background" is already in the screen gamma, while "background_1" is 1.2705 + * at a gamma of 1.0. Paletted files have already been taken care of. 1.2706 + */ 1.2707 +void /* PRIVATE */ 1.2708 +png_do_background(png_row_infop row_info, png_bytep row, 1.2709 + png_color_16p trans_values, png_color_16p background 1.2710 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2711 + , png_color_16p background_1, 1.2712 + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, 1.2713 + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, 1.2714 + png_uint_16pp gamma_16_to_1, int gamma_shift 1.2715 +#endif 1.2716 + ) 1.2717 +{ 1.2718 + png_bytep sp, dp; 1.2719 + png_uint_32 i; 1.2720 + png_uint_32 row_width=row_info->width; 1.2721 + int shift; 1.2722 + 1.2723 + png_debug(1, "in png_do_background\n"); 1.2724 + if (background != NULL && 1.2725 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.2726 + row != NULL && row_info != NULL && 1.2727 +#endif 1.2728 + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || 1.2729 + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) 1.2730 + { 1.2731 + switch (row_info->color_type) 1.2732 + { 1.2733 + case PNG_COLOR_TYPE_GRAY: 1.2734 + { 1.2735 + switch (row_info->bit_depth) 1.2736 + { 1.2737 + case 1: 1.2738 + { 1.2739 + sp = row; 1.2740 + shift = 7; 1.2741 + for (i = 0; i < row_width; i++) 1.2742 + { 1.2743 + if ((png_uint_16)((*sp >> shift) & 0x01) 1.2744 + == trans_values->gray) 1.2745 + { 1.2746 + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); 1.2747 + *sp |= (png_byte)(background->gray << shift); 1.2748 + } 1.2749 + if (!shift) 1.2750 + { 1.2751 + shift = 7; 1.2752 + sp++; 1.2753 + } 1.2754 + else 1.2755 + shift--; 1.2756 + } 1.2757 + break; 1.2758 + } 1.2759 + case 2: 1.2760 + { 1.2761 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2762 + if (gamma_table != NULL) 1.2763 + { 1.2764 + sp = row; 1.2765 + shift = 6; 1.2766 + for (i = 0; i < row_width; i++) 1.2767 + { 1.2768 + if ((png_uint_16)((*sp >> shift) & 0x03) 1.2769 + == trans_values->gray) 1.2770 + { 1.2771 + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 1.2772 + *sp |= (png_byte)(background->gray << shift); 1.2773 + } 1.2774 + else 1.2775 + { 1.2776 + png_byte p = (png_byte)((*sp >> shift) & 0x03); 1.2777 + png_byte g = (png_byte)((gamma_table [p | (p << 2) | 1.2778 + (p << 4) | (p << 6)] >> 6) & 0x03); 1.2779 + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 1.2780 + *sp |= (png_byte)(g << shift); 1.2781 + } 1.2782 + if (!shift) 1.2783 + { 1.2784 + shift = 6; 1.2785 + sp++; 1.2786 + } 1.2787 + else 1.2788 + shift -= 2; 1.2789 + } 1.2790 + } 1.2791 + else 1.2792 +#endif 1.2793 + { 1.2794 + sp = row; 1.2795 + shift = 6; 1.2796 + for (i = 0; i < row_width; i++) 1.2797 + { 1.2798 + if ((png_uint_16)((*sp >> shift) & 0x03) 1.2799 + == trans_values->gray) 1.2800 + { 1.2801 + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 1.2802 + *sp |= (png_byte)(background->gray << shift); 1.2803 + } 1.2804 + if (!shift) 1.2805 + { 1.2806 + shift = 6; 1.2807 + sp++; 1.2808 + } 1.2809 + else 1.2810 + shift -= 2; 1.2811 + } 1.2812 + } 1.2813 + break; 1.2814 + } 1.2815 + case 4: 1.2816 + { 1.2817 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2818 + if (gamma_table != NULL) 1.2819 + { 1.2820 + sp = row; 1.2821 + shift = 4; 1.2822 + for (i = 0; i < row_width; i++) 1.2823 + { 1.2824 + if ((png_uint_16)((*sp >> shift) & 0x0f) 1.2825 + == trans_values->gray) 1.2826 + { 1.2827 + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 1.2828 + *sp |= (png_byte)(background->gray << shift); 1.2829 + } 1.2830 + else 1.2831 + { 1.2832 + png_byte p = (png_byte)((*sp >> shift) & 0x0f); 1.2833 + png_byte g = (png_byte)((gamma_table[p | 1.2834 + (p << 4)] >> 4) & 0x0f); 1.2835 + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 1.2836 + *sp |= (png_byte)(g << shift); 1.2837 + } 1.2838 + if (!shift) 1.2839 + { 1.2840 + shift = 4; 1.2841 + sp++; 1.2842 + } 1.2843 + else 1.2844 + shift -= 4; 1.2845 + } 1.2846 + } 1.2847 + else 1.2848 +#endif 1.2849 + { 1.2850 + sp = row; 1.2851 + shift = 4; 1.2852 + for (i = 0; i < row_width; i++) 1.2853 + { 1.2854 + if ((png_uint_16)((*sp >> shift) & 0x0f) 1.2855 + == trans_values->gray) 1.2856 + { 1.2857 + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 1.2858 + *sp |= (png_byte)(background->gray << shift); 1.2859 + } 1.2860 + if (!shift) 1.2861 + { 1.2862 + shift = 4; 1.2863 + sp++; 1.2864 + } 1.2865 + else 1.2866 + shift -= 4; 1.2867 + } 1.2868 + } 1.2869 + break; 1.2870 + } 1.2871 + case 8: 1.2872 + { 1.2873 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2874 + if (gamma_table != NULL) 1.2875 + { 1.2876 + sp = row; 1.2877 + for (i = 0; i < row_width; i++, sp++) 1.2878 + { 1.2879 + if (*sp == trans_values->gray) 1.2880 + { 1.2881 + *sp = (png_byte)background->gray; 1.2882 + } 1.2883 + else 1.2884 + { 1.2885 + *sp = gamma_table[*sp]; 1.2886 + } 1.2887 + } 1.2888 + } 1.2889 + else 1.2890 +#endif 1.2891 + { 1.2892 + sp = row; 1.2893 + for (i = 0; i < row_width; i++, sp++) 1.2894 + { 1.2895 + if (*sp == trans_values->gray) 1.2896 + { 1.2897 + *sp = (png_byte)background->gray; 1.2898 + } 1.2899 + } 1.2900 + } 1.2901 + break; 1.2902 + } 1.2903 + case 16: 1.2904 + { 1.2905 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2906 + if (gamma_16 != NULL) 1.2907 + { 1.2908 + sp = row; 1.2909 + for (i = 0; i < row_width; i++, sp += 2) 1.2910 + { 1.2911 + png_uint_16 v; 1.2912 + 1.2913 + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.2914 + if (v == trans_values->gray) 1.2915 + { 1.2916 + /* background is already in screen gamma */ 1.2917 + *sp = (png_byte)((background->gray >> 8) & 0xff); 1.2918 + *(sp + 1) = (png_byte)(background->gray & 0xff); 1.2919 + } 1.2920 + else 1.2921 + { 1.2922 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.2923 + *sp = (png_byte)((v >> 8) & 0xff); 1.2924 + *(sp + 1) = (png_byte)(v & 0xff); 1.2925 + } 1.2926 + } 1.2927 + } 1.2928 + else 1.2929 +#endif 1.2930 + { 1.2931 + sp = row; 1.2932 + for (i = 0; i < row_width; i++, sp += 2) 1.2933 + { 1.2934 + png_uint_16 v; 1.2935 + 1.2936 + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.2937 + if (v == trans_values->gray) 1.2938 + { 1.2939 + *sp = (png_byte)((background->gray >> 8) & 0xff); 1.2940 + *(sp + 1) = (png_byte)(background->gray & 0xff); 1.2941 + } 1.2942 + } 1.2943 + } 1.2944 + break; 1.2945 + } 1.2946 + } 1.2947 + break; 1.2948 + } 1.2949 + case PNG_COLOR_TYPE_RGB: 1.2950 + { 1.2951 + if (row_info->bit_depth == 8) 1.2952 + { 1.2953 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2954 + if (gamma_table != NULL) 1.2955 + { 1.2956 + sp = row; 1.2957 + for (i = 0; i < row_width; i++, sp += 3) 1.2958 + { 1.2959 + if (*sp == trans_values->red && 1.2960 + *(sp + 1) == trans_values->green && 1.2961 + *(sp + 2) == trans_values->blue) 1.2962 + { 1.2963 + *sp = (png_byte)background->red; 1.2964 + *(sp + 1) = (png_byte)background->green; 1.2965 + *(sp + 2) = (png_byte)background->blue; 1.2966 + } 1.2967 + else 1.2968 + { 1.2969 + *sp = gamma_table[*sp]; 1.2970 + *(sp + 1) = gamma_table[*(sp + 1)]; 1.2971 + *(sp + 2) = gamma_table[*(sp + 2)]; 1.2972 + } 1.2973 + } 1.2974 + } 1.2975 + else 1.2976 +#endif 1.2977 + { 1.2978 + sp = row; 1.2979 + for (i = 0; i < row_width; i++, sp += 3) 1.2980 + { 1.2981 + if (*sp == trans_values->red && 1.2982 + *(sp + 1) == trans_values->green && 1.2983 + *(sp + 2) == trans_values->blue) 1.2984 + { 1.2985 + *sp = (png_byte)background->red; 1.2986 + *(sp + 1) = (png_byte)background->green; 1.2987 + *(sp + 2) = (png_byte)background->blue; 1.2988 + } 1.2989 + } 1.2990 + } 1.2991 + } 1.2992 + else /* if (row_info->bit_depth == 16) */ 1.2993 + { 1.2994 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.2995 + if (gamma_16 != NULL) 1.2996 + { 1.2997 + sp = row; 1.2998 + for (i = 0; i < row_width; i++, sp += 6) 1.2999 + { 1.3000 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3001 + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 1.3002 + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 1.3003 + if (r == trans_values->red && g == trans_values->green && 1.3004 + b == trans_values->blue) 1.3005 + { 1.3006 + /* background is already in screen gamma */ 1.3007 + *sp = (png_byte)((background->red >> 8) & 0xff); 1.3008 + *(sp + 1) = (png_byte)(background->red & 0xff); 1.3009 + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 1.3010 + *(sp + 3) = (png_byte)(background->green & 0xff); 1.3011 + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 1.3012 + *(sp + 5) = (png_byte)(background->blue & 0xff); 1.3013 + } 1.3014 + else 1.3015 + { 1.3016 + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3017 + *sp = (png_byte)((v >> 8) & 0xff); 1.3018 + *(sp + 1) = (png_byte)(v & 0xff); 1.3019 + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3020 + *(sp + 2) = (png_byte)((v >> 8) & 0xff); 1.3021 + *(sp + 3) = (png_byte)(v & 0xff); 1.3022 + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3023 + *(sp + 4) = (png_byte)((v >> 8) & 0xff); 1.3024 + *(sp + 5) = (png_byte)(v & 0xff); 1.3025 + } 1.3026 + } 1.3027 + } 1.3028 + else 1.3029 +#endif 1.3030 + { 1.3031 + sp = row; 1.3032 + for (i = 0; i < row_width; i++, sp += 6) 1.3033 + { 1.3034 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); 1.3035 + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 1.3036 + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 1.3037 + 1.3038 + if (r == trans_values->red && g == trans_values->green && 1.3039 + b == trans_values->blue) 1.3040 + { 1.3041 + *sp = (png_byte)((background->red >> 8) & 0xff); 1.3042 + *(sp + 1) = (png_byte)(background->red & 0xff); 1.3043 + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 1.3044 + *(sp + 3) = (png_byte)(background->green & 0xff); 1.3045 + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 1.3046 + *(sp + 5) = (png_byte)(background->blue & 0xff); 1.3047 + } 1.3048 + } 1.3049 + } 1.3050 + } 1.3051 + break; 1.3052 + } 1.3053 + case PNG_COLOR_TYPE_GRAY_ALPHA: 1.3054 + { 1.3055 + if (row_info->bit_depth == 8) 1.3056 + { 1.3057 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3058 + if (gamma_to_1 != NULL && gamma_from_1 != NULL && 1.3059 + gamma_table != NULL) 1.3060 + { 1.3061 + sp = row; 1.3062 + dp = row; 1.3063 + for (i = 0; i < row_width; i++, sp += 2, dp++) 1.3064 + { 1.3065 + png_uint_16 a = *(sp + 1); 1.3066 + 1.3067 + if (a == 0xff) 1.3068 + { 1.3069 + *dp = gamma_table[*sp]; 1.3070 + } 1.3071 + else if (a == 0) 1.3072 + { 1.3073 + /* background is already in screen gamma */ 1.3074 + *dp = (png_byte)background->gray; 1.3075 + } 1.3076 + else 1.3077 + { 1.3078 + png_byte v, w; 1.3079 + 1.3080 + v = gamma_to_1[*sp]; 1.3081 + png_composite(w, v, a, background_1->gray); 1.3082 + *dp = gamma_from_1[w]; 1.3083 + } 1.3084 + } 1.3085 + } 1.3086 + else 1.3087 +#endif 1.3088 + { 1.3089 + sp = row; 1.3090 + dp = row; 1.3091 + for (i = 0; i < row_width; i++, sp += 2, dp++) 1.3092 + { 1.3093 + png_byte a = *(sp + 1); 1.3094 + 1.3095 + if (a == 0xff) 1.3096 + { 1.3097 + *dp = *sp; 1.3098 + } 1.3099 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3100 + else if (a == 0) 1.3101 + { 1.3102 + *dp = (png_byte)background->gray; 1.3103 + } 1.3104 + else 1.3105 + { 1.3106 + png_composite(*dp, *sp, a, background_1->gray); 1.3107 + } 1.3108 +#else 1.3109 + *dp = (png_byte)background->gray; 1.3110 +#endif 1.3111 + } 1.3112 + } 1.3113 + } 1.3114 + else /* if (png_ptr->bit_depth == 16) */ 1.3115 + { 1.3116 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3117 + if (gamma_16 != NULL && gamma_16_from_1 != NULL && 1.3118 + gamma_16_to_1 != NULL) 1.3119 + { 1.3120 + sp = row; 1.3121 + dp = row; 1.3122 + for (i = 0; i < row_width; i++, sp += 4, dp += 2) 1.3123 + { 1.3124 + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 1.3125 + 1.3126 + if (a == (png_uint_16)0xffff) 1.3127 + { 1.3128 + png_uint_16 v; 1.3129 + 1.3130 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3131 + *dp = (png_byte)((v >> 8) & 0xff); 1.3132 + *(dp + 1) = (png_byte)(v & 0xff); 1.3133 + } 1.3134 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3135 + else if (a == 0) 1.3136 +#else 1.3137 + else 1.3138 +#endif 1.3139 + { 1.3140 + /* background is already in screen gamma */ 1.3141 + *dp = (png_byte)((background->gray >> 8) & 0xff); 1.3142 + *(dp + 1) = (png_byte)(background->gray & 0xff); 1.3143 + } 1.3144 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3145 + else 1.3146 + { 1.3147 + png_uint_16 g, v, w; 1.3148 + 1.3149 + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 1.3150 + png_composite_16(v, g, a, background_1->gray); 1.3151 + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; 1.3152 + *dp = (png_byte)((w >> 8) & 0xff); 1.3153 + *(dp + 1) = (png_byte)(w & 0xff); 1.3154 + } 1.3155 +#endif 1.3156 + } 1.3157 + } 1.3158 + else 1.3159 +#endif 1.3160 + { 1.3161 + sp = row; 1.3162 + dp = row; 1.3163 + for (i = 0; i < row_width; i++, sp += 4, dp += 2) 1.3164 + { 1.3165 + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 1.3166 + if (a == (png_uint_16)0xffff) 1.3167 + { 1.3168 + png_memcpy(dp, sp, 2); 1.3169 + } 1.3170 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3171 + else if (a == 0) 1.3172 +#else 1.3173 + else 1.3174 +#endif 1.3175 + { 1.3176 + *dp = (png_byte)((background->gray >> 8) & 0xff); 1.3177 + *(dp + 1) = (png_byte)(background->gray & 0xff); 1.3178 + } 1.3179 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3180 + else 1.3181 + { 1.3182 + png_uint_16 g, v; 1.3183 + 1.3184 + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3185 + png_composite_16(v, g, a, background_1->gray); 1.3186 + *dp = (png_byte)((v >> 8) & 0xff); 1.3187 + *(dp + 1) = (png_byte)(v & 0xff); 1.3188 + } 1.3189 +#endif 1.3190 + } 1.3191 + } 1.3192 + } 1.3193 + break; 1.3194 + } 1.3195 + case PNG_COLOR_TYPE_RGB_ALPHA: 1.3196 + { 1.3197 + if (row_info->bit_depth == 8) 1.3198 + { 1.3199 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3200 + if (gamma_to_1 != NULL && gamma_from_1 != NULL && 1.3201 + gamma_table != NULL) 1.3202 + { 1.3203 + sp = row; 1.3204 + dp = row; 1.3205 + for (i = 0; i < row_width; i++, sp += 4, dp += 3) 1.3206 + { 1.3207 + png_byte a = *(sp + 3); 1.3208 + 1.3209 + if (a == 0xff) 1.3210 + { 1.3211 + *dp = gamma_table[*sp]; 1.3212 + *(dp + 1) = gamma_table[*(sp + 1)]; 1.3213 + *(dp + 2) = gamma_table[*(sp + 2)]; 1.3214 + } 1.3215 + else if (a == 0) 1.3216 + { 1.3217 + /* background is already in screen gamma */ 1.3218 + *dp = (png_byte)background->red; 1.3219 + *(dp + 1) = (png_byte)background->green; 1.3220 + *(dp + 2) = (png_byte)background->blue; 1.3221 + } 1.3222 + else 1.3223 + { 1.3224 + png_byte v, w; 1.3225 + 1.3226 + v = gamma_to_1[*sp]; 1.3227 + png_composite(w, v, a, background_1->red); 1.3228 + *dp = gamma_from_1[w]; 1.3229 + v = gamma_to_1[*(sp + 1)]; 1.3230 + png_composite(w, v, a, background_1->green); 1.3231 + *(dp + 1) = gamma_from_1[w]; 1.3232 + v = gamma_to_1[*(sp + 2)]; 1.3233 + png_composite(w, v, a, background_1->blue); 1.3234 + *(dp + 2) = gamma_from_1[w]; 1.3235 + } 1.3236 + } 1.3237 + } 1.3238 + else 1.3239 +#endif 1.3240 + { 1.3241 + sp = row; 1.3242 + dp = row; 1.3243 + for (i = 0; i < row_width; i++, sp += 4, dp += 3) 1.3244 + { 1.3245 + png_byte a = *(sp + 3); 1.3246 + 1.3247 + if (a == 0xff) 1.3248 + { 1.3249 + *dp = *sp; 1.3250 + *(dp + 1) = *(sp + 1); 1.3251 + *(dp + 2) = *(sp + 2); 1.3252 + } 1.3253 + else if (a == 0) 1.3254 + { 1.3255 + *dp = (png_byte)background->red; 1.3256 + *(dp + 1) = (png_byte)background->green; 1.3257 + *(dp + 2) = (png_byte)background->blue; 1.3258 + } 1.3259 + else 1.3260 + { 1.3261 + png_composite(*dp, *sp, a, background->red); 1.3262 + png_composite(*(dp + 1), *(sp + 1), a, 1.3263 + background->green); 1.3264 + png_composite(*(dp + 2), *(sp + 2), a, 1.3265 + background->blue); 1.3266 + } 1.3267 + } 1.3268 + } 1.3269 + } 1.3270 + else /* if (row_info->bit_depth == 16) */ 1.3271 + { 1.3272 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3273 + if (gamma_16 != NULL && gamma_16_from_1 != NULL && 1.3274 + gamma_16_to_1 != NULL) 1.3275 + { 1.3276 + sp = row; 1.3277 + dp = row; 1.3278 + for (i = 0; i < row_width; i++, sp += 8, dp += 6) 1.3279 + { 1.3280 + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 1.3281 + << 8) + (png_uint_16)(*(sp + 7))); 1.3282 + if (a == (png_uint_16)0xffff) 1.3283 + { 1.3284 + png_uint_16 v; 1.3285 + 1.3286 + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 1.3287 + *dp = (png_byte)((v >> 8) & 0xff); 1.3288 + *(dp + 1) = (png_byte)(v & 0xff); 1.3289 + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3290 + *(dp + 2) = (png_byte)((v >> 8) & 0xff); 1.3291 + *(dp + 3) = (png_byte)(v & 0xff); 1.3292 + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3293 + *(dp + 4) = (png_byte)((v >> 8) & 0xff); 1.3294 + *(dp + 5) = (png_byte)(v & 0xff); 1.3295 + } 1.3296 + else if (a == 0) 1.3297 + { 1.3298 + /* background is already in screen gamma */ 1.3299 + *dp = (png_byte)((background->red >> 8) & 0xff); 1.3300 + *(dp + 1) = (png_byte)(background->red & 0xff); 1.3301 + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 1.3302 + *(dp + 3) = (png_byte)(background->green & 0xff); 1.3303 + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 1.3304 + *(dp + 5) = (png_byte)(background->blue & 0xff); 1.3305 + } 1.3306 + else 1.3307 + { 1.3308 + png_uint_16 v, w, x; 1.3309 + 1.3310 + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 1.3311 + png_composite_16(w, v, a, background_1->red); 1.3312 + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 1.3313 + *dp = (png_byte)((x >> 8) & 0xff); 1.3314 + *(dp + 1) = (png_byte)(x & 0xff); 1.3315 + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 1.3316 + png_composite_16(w, v, a, background_1->green); 1.3317 + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 1.3318 + *(dp + 2) = (png_byte)((x >> 8) & 0xff); 1.3319 + *(dp + 3) = (png_byte)(x & 0xff); 1.3320 + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 1.3321 + png_composite_16(w, v, a, background_1->blue); 1.3322 + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; 1.3323 + *(dp + 4) = (png_byte)((x >> 8) & 0xff); 1.3324 + *(dp + 5) = (png_byte)(x & 0xff); 1.3325 + } 1.3326 + } 1.3327 + } 1.3328 + else 1.3329 +#endif 1.3330 + { 1.3331 + sp = row; 1.3332 + dp = row; 1.3333 + for (i = 0; i < row_width; i++, sp += 8, dp += 6) 1.3334 + { 1.3335 + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 1.3336 + << 8) + (png_uint_16)(*(sp + 7))); 1.3337 + if (a == (png_uint_16)0xffff) 1.3338 + { 1.3339 + png_memcpy(dp, sp, 6); 1.3340 + } 1.3341 + else if (a == 0) 1.3342 + { 1.3343 + *dp = (png_byte)((background->red >> 8) & 0xff); 1.3344 + *(dp + 1) = (png_byte)(background->red & 0xff); 1.3345 + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 1.3346 + *(dp + 3) = (png_byte)(background->green & 0xff); 1.3347 + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 1.3348 + *(dp + 5) = (png_byte)(background->blue & 0xff); 1.3349 + } 1.3350 + else 1.3351 + { 1.3352 + png_uint_16 v; 1.3353 + 1.3354 + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 1.3355 + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 1.3356 + + *(sp + 3)); 1.3357 + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 1.3358 + + *(sp + 5)); 1.3359 + 1.3360 + png_composite_16(v, r, a, background->red); 1.3361 + *dp = (png_byte)((v >> 8) & 0xff); 1.3362 + *(dp + 1) = (png_byte)(v & 0xff); 1.3363 + png_composite_16(v, g, a, background->green); 1.3364 + *(dp + 2) = (png_byte)((v >> 8) & 0xff); 1.3365 + *(dp + 3) = (png_byte)(v & 0xff); 1.3366 + png_composite_16(v, b, a, background->blue); 1.3367 + *(dp + 4) = (png_byte)((v >> 8) & 0xff); 1.3368 + *(dp + 5) = (png_byte)(v & 0xff); 1.3369 + } 1.3370 + } 1.3371 + } 1.3372 + } 1.3373 + break; 1.3374 + } 1.3375 + } 1.3376 + 1.3377 + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 1.3378 + { 1.3379 + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; 1.3380 + row_info->channels--; 1.3381 + row_info->pixel_depth = (png_byte)(row_info->channels * 1.3382 + row_info->bit_depth); 1.3383 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.3384 + } 1.3385 + } 1.3386 +} 1.3387 +#endif 1.3388 + 1.3389 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.3390 +/* Gamma correct the image, avoiding the alpha channel. Make sure 1.3391 + * you do this after you deal with the transparency issue on grayscale 1.3392 + * or RGB images. If your bit depth is 8, use gamma_table, if it 1.3393 + * is 16, use gamma_16_table and gamma_shift. Build these with 1.3394 + * build_gamma_table(). 1.3395 + */ 1.3396 +void /* PRIVATE */ 1.3397 +png_do_gamma(png_row_infop row_info, png_bytep row, 1.3398 + png_bytep gamma_table, png_uint_16pp gamma_16_table, 1.3399 + int gamma_shift) 1.3400 +{ 1.3401 + png_bytep sp; 1.3402 + png_uint_32 i; 1.3403 + png_uint_32 row_width=row_info->width; 1.3404 + 1.3405 + png_debug(1, "in png_do_gamma\n"); 1.3406 + if ( 1.3407 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.3408 + row != NULL && row_info != NULL && 1.3409 +#endif 1.3410 + ((row_info->bit_depth <= 8 && gamma_table != NULL) || 1.3411 + (row_info->bit_depth == 16 && gamma_16_table != NULL))) 1.3412 + { 1.3413 + switch (row_info->color_type) 1.3414 + { 1.3415 + case PNG_COLOR_TYPE_RGB: 1.3416 + { 1.3417 + if (row_info->bit_depth == 8) 1.3418 + { 1.3419 + sp = row; 1.3420 + for (i = 0; i < row_width; i++) 1.3421 + { 1.3422 + *sp = gamma_table[*sp]; 1.3423 + sp++; 1.3424 + *sp = gamma_table[*sp]; 1.3425 + sp++; 1.3426 + *sp = gamma_table[*sp]; 1.3427 + sp++; 1.3428 + } 1.3429 + } 1.3430 + else /* if (row_info->bit_depth == 16) */ 1.3431 + { 1.3432 + sp = row; 1.3433 + for (i = 0; i < row_width; i++) 1.3434 + { 1.3435 + png_uint_16 v; 1.3436 + 1.3437 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3438 + *sp = (png_byte)((v >> 8) & 0xff); 1.3439 + *(sp + 1) = (png_byte)(v & 0xff); 1.3440 + sp += 2; 1.3441 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3442 + *sp = (png_byte)((v >> 8) & 0xff); 1.3443 + *(sp + 1) = (png_byte)(v & 0xff); 1.3444 + sp += 2; 1.3445 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3446 + *sp = (png_byte)((v >> 8) & 0xff); 1.3447 + *(sp + 1) = (png_byte)(v & 0xff); 1.3448 + sp += 2; 1.3449 + } 1.3450 + } 1.3451 + break; 1.3452 + } 1.3453 + case PNG_COLOR_TYPE_RGB_ALPHA: 1.3454 + { 1.3455 + if (row_info->bit_depth == 8) 1.3456 + { 1.3457 + sp = row; 1.3458 + for (i = 0; i < row_width; i++) 1.3459 + { 1.3460 + *sp = gamma_table[*sp]; 1.3461 + sp++; 1.3462 + *sp = gamma_table[*sp]; 1.3463 + sp++; 1.3464 + *sp = gamma_table[*sp]; 1.3465 + sp++; 1.3466 + sp++; 1.3467 + } 1.3468 + } 1.3469 + else /* if (row_info->bit_depth == 16) */ 1.3470 + { 1.3471 + sp = row; 1.3472 + for (i = 0; i < row_width; i++) 1.3473 + { 1.3474 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3475 + *sp = (png_byte)((v >> 8) & 0xff); 1.3476 + *(sp + 1) = (png_byte)(v & 0xff); 1.3477 + sp += 2; 1.3478 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3479 + *sp = (png_byte)((v >> 8) & 0xff); 1.3480 + *(sp + 1) = (png_byte)(v & 0xff); 1.3481 + sp += 2; 1.3482 + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3483 + *sp = (png_byte)((v >> 8) & 0xff); 1.3484 + *(sp + 1) = (png_byte)(v & 0xff); 1.3485 + sp += 4; 1.3486 + } 1.3487 + } 1.3488 + break; 1.3489 + } 1.3490 + case PNG_COLOR_TYPE_GRAY_ALPHA: 1.3491 + { 1.3492 + if (row_info->bit_depth == 8) 1.3493 + { 1.3494 + sp = row; 1.3495 + for (i = 0; i < row_width; i++) 1.3496 + { 1.3497 + *sp = gamma_table[*sp]; 1.3498 + sp += 2; 1.3499 + } 1.3500 + } 1.3501 + else /* if (row_info->bit_depth == 16) */ 1.3502 + { 1.3503 + sp = row; 1.3504 + for (i = 0; i < row_width; i++) 1.3505 + { 1.3506 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3507 + *sp = (png_byte)((v >> 8) & 0xff); 1.3508 + *(sp + 1) = (png_byte)(v & 0xff); 1.3509 + sp += 4; 1.3510 + } 1.3511 + } 1.3512 + break; 1.3513 + } 1.3514 + case PNG_COLOR_TYPE_GRAY: 1.3515 + { 1.3516 + if (row_info->bit_depth == 2) 1.3517 + { 1.3518 + sp = row; 1.3519 + for (i = 0; i < row_width; i += 4) 1.3520 + { 1.3521 + int a = *sp & 0xc0; 1.3522 + int b = *sp & 0x30; 1.3523 + int c = *sp & 0x0c; 1.3524 + int d = *sp & 0x03; 1.3525 + 1.3526 + *sp = (png_byte)( 1.3527 + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 1.3528 + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 1.3529 + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 1.3530 + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 1.3531 + sp++; 1.3532 + } 1.3533 + } 1.3534 + if (row_info->bit_depth == 4) 1.3535 + { 1.3536 + sp = row; 1.3537 + for (i = 0; i < row_width; i += 2) 1.3538 + { 1.3539 + int msb = *sp & 0xf0; 1.3540 + int lsb = *sp & 0x0f; 1.3541 + 1.3542 + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 1.3543 + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 1.3544 + sp++; 1.3545 + } 1.3546 + } 1.3547 + else if (row_info->bit_depth == 8) 1.3548 + { 1.3549 + sp = row; 1.3550 + for (i = 0; i < row_width; i++) 1.3551 + { 1.3552 + *sp = gamma_table[*sp]; 1.3553 + sp++; 1.3554 + } 1.3555 + } 1.3556 + else if (row_info->bit_depth == 16) 1.3557 + { 1.3558 + sp = row; 1.3559 + for (i = 0; i < row_width; i++) 1.3560 + { 1.3561 + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 1.3562 + *sp = (png_byte)((v >> 8) & 0xff); 1.3563 + *(sp + 1) = (png_byte)(v & 0xff); 1.3564 + sp += 2; 1.3565 + } 1.3566 + } 1.3567 + break; 1.3568 + } 1.3569 + } 1.3570 + } 1.3571 +} 1.3572 +#endif 1.3573 + 1.3574 +#if defined(PNG_READ_EXPAND_SUPPORTED) 1.3575 +/* Expands a palette row to an RGB or RGBA row depending 1.3576 + * upon whether you supply trans and num_trans. 1.3577 + */ 1.3578 +void /* PRIVATE */ 1.3579 +png_do_expand_palette(png_row_infop row_info, png_bytep row, 1.3580 + png_colorp palette, png_bytep trans, int num_trans) 1.3581 +{ 1.3582 + int shift, value; 1.3583 + png_bytep sp, dp; 1.3584 + png_uint_32 i; 1.3585 + png_uint_32 row_width=row_info->width; 1.3586 + 1.3587 + png_debug(1, "in png_do_expand_palette\n"); 1.3588 + if ( 1.3589 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.3590 + row != NULL && row_info != NULL && 1.3591 +#endif 1.3592 + row_info->color_type == PNG_COLOR_TYPE_PALETTE) 1.3593 + { 1.3594 + if (row_info->bit_depth < 8) 1.3595 + { 1.3596 + switch (row_info->bit_depth) 1.3597 + { 1.3598 + case 1: 1.3599 + { 1.3600 + sp = row + (png_size_t)((row_width - 1) >> 3); 1.3601 + dp = row + (png_size_t)row_width - 1; 1.3602 + shift = 7 - (int)((row_width + 7) & 0x07); 1.3603 + for (i = 0; i < row_width; i++) 1.3604 + { 1.3605 + if ((*sp >> shift) & 0x01) 1.3606 + *dp = 1; 1.3607 + else 1.3608 + *dp = 0; 1.3609 + if (shift == 7) 1.3610 + { 1.3611 + shift = 0; 1.3612 + sp--; 1.3613 + } 1.3614 + else 1.3615 + shift++; 1.3616 + 1.3617 + dp--; 1.3618 + } 1.3619 + break; 1.3620 + } 1.3621 + case 2: 1.3622 + { 1.3623 + sp = row + (png_size_t)((row_width - 1) >> 2); 1.3624 + dp = row + (png_size_t)row_width - 1; 1.3625 + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.3626 + for (i = 0; i < row_width; i++) 1.3627 + { 1.3628 + value = (*sp >> shift) & 0x03; 1.3629 + *dp = (png_byte)value; 1.3630 + if (shift == 6) 1.3631 + { 1.3632 + shift = 0; 1.3633 + sp--; 1.3634 + } 1.3635 + else 1.3636 + shift += 2; 1.3637 + 1.3638 + dp--; 1.3639 + } 1.3640 + break; 1.3641 + } 1.3642 + case 4: 1.3643 + { 1.3644 + sp = row + (png_size_t)((row_width - 1) >> 1); 1.3645 + dp = row + (png_size_t)row_width - 1; 1.3646 + shift = (int)((row_width & 0x01) << 2); 1.3647 + for (i = 0; i < row_width; i++) 1.3648 + { 1.3649 + value = (*sp >> shift) & 0x0f; 1.3650 + *dp = (png_byte)value; 1.3651 + if (shift == 4) 1.3652 + { 1.3653 + shift = 0; 1.3654 + sp--; 1.3655 + } 1.3656 + else 1.3657 + shift += 4; 1.3658 + 1.3659 + dp--; 1.3660 + } 1.3661 + break; 1.3662 + } 1.3663 + } 1.3664 + row_info->bit_depth = 8; 1.3665 + row_info->pixel_depth = 8; 1.3666 + row_info->rowbytes = row_width; 1.3667 + } 1.3668 + switch (row_info->bit_depth) 1.3669 + { 1.3670 + case 8: 1.3671 + { 1.3672 + if (trans != NULL) 1.3673 + { 1.3674 + sp = row + (png_size_t)row_width - 1; 1.3675 + dp = row + (png_size_t)(row_width << 2) - 1; 1.3676 + 1.3677 + for (i = 0; i < row_width; i++) 1.3678 + { 1.3679 + if ((int)(*sp) >= num_trans) 1.3680 + *dp-- = 0xff; 1.3681 + else 1.3682 + *dp-- = trans[*sp]; 1.3683 + *dp-- = palette[*sp].blue; 1.3684 + *dp-- = palette[*sp].green; 1.3685 + *dp-- = palette[*sp].red; 1.3686 + sp--; 1.3687 + } 1.3688 + row_info->bit_depth = 8; 1.3689 + row_info->pixel_depth = 32; 1.3690 + row_info->rowbytes = row_width * 4; 1.3691 + row_info->color_type = 6; 1.3692 + row_info->channels = 4; 1.3693 + } 1.3694 + else 1.3695 + { 1.3696 + sp = row + (png_size_t)row_width - 1; 1.3697 + dp = row + (png_size_t)(row_width * 3) - 1; 1.3698 + 1.3699 + for (i = 0; i < row_width; i++) 1.3700 + { 1.3701 + *dp-- = palette[*sp].blue; 1.3702 + *dp-- = palette[*sp].green; 1.3703 + *dp-- = palette[*sp].red; 1.3704 + sp--; 1.3705 + } 1.3706 + row_info->bit_depth = 8; 1.3707 + row_info->pixel_depth = 24; 1.3708 + row_info->rowbytes = row_width * 3; 1.3709 + row_info->color_type = 2; 1.3710 + row_info->channels = 3; 1.3711 + } 1.3712 + break; 1.3713 + } 1.3714 + } 1.3715 + } 1.3716 +} 1.3717 + 1.3718 +/* If the bit depth < 8, it is expanded to 8. Also, if the already 1.3719 + * expanded transparency value is supplied, an alpha channel is built. 1.3720 + */ 1.3721 +void /* PRIVATE */ 1.3722 +png_do_expand(png_row_infop row_info, png_bytep row, 1.3723 + png_color_16p trans_value) 1.3724 +{ 1.3725 + int shift, value; 1.3726 + png_bytep sp, dp; 1.3727 + png_uint_32 i; 1.3728 + png_uint_32 row_width=row_info->width; 1.3729 + 1.3730 + png_debug(1, "in png_do_expand\n"); 1.3731 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.3732 + if (row != NULL && row_info != NULL) 1.3733 +#endif 1.3734 + { 1.3735 + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 1.3736 + { 1.3737 + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); 1.3738 + 1.3739 + if (row_info->bit_depth < 8) 1.3740 + { 1.3741 + switch (row_info->bit_depth) 1.3742 + { 1.3743 + case 1: 1.3744 + { 1.3745 + gray = (png_uint_16)((gray&0x01)*0xff); 1.3746 + sp = row + (png_size_t)((row_width - 1) >> 3); 1.3747 + dp = row + (png_size_t)row_width - 1; 1.3748 + shift = 7 - (int)((row_width + 7) & 0x07); 1.3749 + for (i = 0; i < row_width; i++) 1.3750 + { 1.3751 + if ((*sp >> shift) & 0x01) 1.3752 + *dp = 0xff; 1.3753 + else 1.3754 + *dp = 0; 1.3755 + if (shift == 7) 1.3756 + { 1.3757 + shift = 0; 1.3758 + sp--; 1.3759 + } 1.3760 + else 1.3761 + shift++; 1.3762 + 1.3763 + dp--; 1.3764 + } 1.3765 + break; 1.3766 + } 1.3767 + case 2: 1.3768 + { 1.3769 + gray = (png_uint_16)((gray&0x03)*0x55); 1.3770 + sp = row + (png_size_t)((row_width - 1) >> 2); 1.3771 + dp = row + (png_size_t)row_width - 1; 1.3772 + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1.3773 + for (i = 0; i < row_width; i++) 1.3774 + { 1.3775 + value = (*sp >> shift) & 0x03; 1.3776 + *dp = (png_byte)(value | (value << 2) | (value << 4) | 1.3777 + (value << 6)); 1.3778 + if (shift == 6) 1.3779 + { 1.3780 + shift = 0; 1.3781 + sp--; 1.3782 + } 1.3783 + else 1.3784 + shift += 2; 1.3785 + 1.3786 + dp--; 1.3787 + } 1.3788 + break; 1.3789 + } 1.3790 + case 4: 1.3791 + { 1.3792 + gray = (png_uint_16)((gray&0x0f)*0x11); 1.3793 + sp = row + (png_size_t)((row_width - 1) >> 1); 1.3794 + dp = row + (png_size_t)row_width - 1; 1.3795 + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 1.3796 + for (i = 0; i < row_width; i++) 1.3797 + { 1.3798 + value = (*sp >> shift) & 0x0f; 1.3799 + *dp = (png_byte)(value | (value << 4)); 1.3800 + if (shift == 4) 1.3801 + { 1.3802 + shift = 0; 1.3803 + sp--; 1.3804 + } 1.3805 + else 1.3806 + shift = 4; 1.3807 + 1.3808 + dp--; 1.3809 + } 1.3810 + break; 1.3811 + } 1.3812 + } 1.3813 + row_info->bit_depth = 8; 1.3814 + row_info->pixel_depth = 8; 1.3815 + row_info->rowbytes = row_width; 1.3816 + } 1.3817 + 1.3818 + if (trans_value != NULL) 1.3819 + { 1.3820 + if (row_info->bit_depth == 8) 1.3821 + { 1.3822 + gray = gray & 0xff; 1.3823 + sp = row + (png_size_t)row_width - 1; 1.3824 + dp = row + (png_size_t)(row_width << 1) - 1; 1.3825 + for (i = 0; i < row_width; i++) 1.3826 + { 1.3827 + if (*sp == gray) 1.3828 + *dp-- = 0; 1.3829 + else 1.3830 + *dp-- = 0xff; 1.3831 + *dp-- = *sp--; 1.3832 + } 1.3833 + } 1.3834 + else if (row_info->bit_depth == 16) 1.3835 + { 1.3836 + png_byte gray_high = (gray >> 8) & 0xff; 1.3837 + png_byte gray_low = gray & 0xff; 1.3838 + sp = row + row_info->rowbytes - 1; 1.3839 + dp = row + (row_info->rowbytes << 1) - 1; 1.3840 + for (i = 0; i < row_width; i++) 1.3841 + { 1.3842 + if (*(sp - 1) == gray_high && *(sp) == gray_low) 1.3843 + { 1.3844 + *dp-- = 0; 1.3845 + *dp-- = 0; 1.3846 + } 1.3847 + else 1.3848 + { 1.3849 + *dp-- = 0xff; 1.3850 + *dp-- = 0xff; 1.3851 + } 1.3852 + *dp-- = *sp--; 1.3853 + *dp-- = *sp--; 1.3854 + } 1.3855 + } 1.3856 + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 1.3857 + row_info->channels = 2; 1.3858 + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 1.3859 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 1.3860 + row_width); 1.3861 + } 1.3862 + } 1.3863 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) 1.3864 + { 1.3865 + if (row_info->bit_depth == 8) 1.3866 + { 1.3867 + png_byte red = trans_value->red & 0xff; 1.3868 + png_byte green = trans_value->green & 0xff; 1.3869 + png_byte blue = trans_value->blue & 0xff; 1.3870 + sp = row + (png_size_t)row_info->rowbytes - 1; 1.3871 + dp = row + (png_size_t)(row_width << 2) - 1; 1.3872 + for (i = 0; i < row_width; i++) 1.3873 + { 1.3874 + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 1.3875 + *dp-- = 0; 1.3876 + else 1.3877 + *dp-- = 0xff; 1.3878 + *dp-- = *sp--; 1.3879 + *dp-- = *sp--; 1.3880 + *dp-- = *sp--; 1.3881 + } 1.3882 + } 1.3883 + else if (row_info->bit_depth == 16) 1.3884 + { 1.3885 + png_byte red_high = (trans_value->red >> 8) & 0xff; 1.3886 + png_byte green_high = (trans_value->green >> 8) & 0xff; 1.3887 + png_byte blue_high = (trans_value->blue >> 8) & 0xff; 1.3888 + png_byte red_low = trans_value->red & 0xff; 1.3889 + png_byte green_low = trans_value->green & 0xff; 1.3890 + png_byte blue_low = trans_value->blue & 0xff; 1.3891 + sp = row + row_info->rowbytes - 1; 1.3892 + dp = row + (png_size_t)(row_width << 3) - 1; 1.3893 + for (i = 0; i < row_width; i++) 1.3894 + { 1.3895 + if (*(sp - 5) == red_high && 1.3896 + *(sp - 4) == red_low && 1.3897 + *(sp - 3) == green_high && 1.3898 + *(sp - 2) == green_low && 1.3899 + *(sp - 1) == blue_high && 1.3900 + *(sp ) == blue_low) 1.3901 + { 1.3902 + *dp-- = 0; 1.3903 + *dp-- = 0; 1.3904 + } 1.3905 + else 1.3906 + { 1.3907 + *dp-- = 0xff; 1.3908 + *dp-- = 0xff; 1.3909 + } 1.3910 + *dp-- = *sp--; 1.3911 + *dp-- = *sp--; 1.3912 + *dp-- = *sp--; 1.3913 + *dp-- = *sp--; 1.3914 + *dp-- = *sp--; 1.3915 + *dp-- = *sp--; 1.3916 + } 1.3917 + } 1.3918 + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1.3919 + row_info->channels = 4; 1.3920 + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 1.3921 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.3922 + } 1.3923 + } 1.3924 +} 1.3925 +#endif 1.3926 + 1.3927 +#if defined(PNG_READ_DITHER_SUPPORTED) 1.3928 +void /* PRIVATE */ 1.3929 +png_do_dither(png_row_infop row_info, png_bytep row, 1.3930 + png_bytep palette_lookup, png_bytep dither_lookup) 1.3931 +{ 1.3932 + png_bytep sp, dp; 1.3933 + png_uint_32 i; 1.3934 + png_uint_32 row_width=row_info->width; 1.3935 + 1.3936 + png_debug(1, "in png_do_dither\n"); 1.3937 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.3938 + if (row != NULL && row_info != NULL) 1.3939 +#endif 1.3940 + { 1.3941 + if (row_info->color_type == PNG_COLOR_TYPE_RGB && 1.3942 + palette_lookup && row_info->bit_depth == 8) 1.3943 + { 1.3944 + int r, g, b, p; 1.3945 + sp = row; 1.3946 + dp = row; 1.3947 + for (i = 0; i < row_width; i++) 1.3948 + { 1.3949 + r = *sp++; 1.3950 + g = *sp++; 1.3951 + b = *sp++; 1.3952 + 1.3953 + /* this looks real messy, but the compiler will reduce 1.3954 + it down to a reasonable formula. For example, with 1.3955 + 5 bits per color, we get: 1.3956 + p = (((r >> 3) & 0x1f) << 10) | 1.3957 + (((g >> 3) & 0x1f) << 5) | 1.3958 + ((b >> 3) & 0x1f); 1.3959 + */ 1.3960 + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 1.3961 + ((1 << PNG_DITHER_RED_BITS) - 1)) << 1.3962 + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 1.3963 + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 1.3964 + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 1.3965 + (PNG_DITHER_BLUE_BITS)) | 1.3966 + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 1.3967 + ((1 << PNG_DITHER_BLUE_BITS) - 1)); 1.3968 + 1.3969 + *dp++ = palette_lookup[p]; 1.3970 + } 1.3971 + row_info->color_type = PNG_COLOR_TYPE_PALETTE; 1.3972 + row_info->channels = 1; 1.3973 + row_info->pixel_depth = row_info->bit_depth; 1.3974 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.3975 + } 1.3976 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 1.3977 + palette_lookup != NULL && row_info->bit_depth == 8) 1.3978 + { 1.3979 + int r, g, b, p; 1.3980 + sp = row; 1.3981 + dp = row; 1.3982 + for (i = 0; i < row_width; i++) 1.3983 + { 1.3984 + r = *sp++; 1.3985 + g = *sp++; 1.3986 + b = *sp++; 1.3987 + sp++; 1.3988 + 1.3989 + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 1.3990 + ((1 << PNG_DITHER_RED_BITS) - 1)) << 1.3991 + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 1.3992 + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 1.3993 + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 1.3994 + (PNG_DITHER_BLUE_BITS)) | 1.3995 + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 1.3996 + ((1 << PNG_DITHER_BLUE_BITS) - 1)); 1.3997 + 1.3998 + *dp++ = palette_lookup[p]; 1.3999 + } 1.4000 + row_info->color_type = PNG_COLOR_TYPE_PALETTE; 1.4001 + row_info->channels = 1; 1.4002 + row_info->pixel_depth = row_info->bit_depth; 1.4003 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 1.4004 + } 1.4005 + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 1.4006 + dither_lookup && row_info->bit_depth == 8) 1.4007 + { 1.4008 + sp = row; 1.4009 + for (i = 0; i < row_width; i++, sp++) 1.4010 + { 1.4011 + *sp = dither_lookup[*sp]; 1.4012 + } 1.4013 + } 1.4014 + } 1.4015 +} 1.4016 +#endif 1.4017 + 1.4018 +#ifdef PNG_FLOATING_POINT_SUPPORTED 1.4019 +#if defined(PNG_READ_GAMMA_SUPPORTED) 1.4020 +static PNG_CONST int png_gamma_shift[] = 1.4021 + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; 1.4022 + 1.4023 +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit 1.4024 + * tables, we don't make a full table if we are reducing to 8-bit in 1.4025 + * the future. Note also how the gamma_16 tables are segmented so that 1.4026 + * we don't need to allocate > 64K chunks for a full 16-bit table. 1.4027 + */ 1.4028 +void /* PRIVATE */ 1.4029 +png_build_gamma_table(png_structp png_ptr) 1.4030 +{ 1.4031 + png_debug(1, "in png_build_gamma_table\n"); 1.4032 + 1.4033 + if (png_ptr->bit_depth <= 8) 1.4034 + { 1.4035 + int i; 1.4036 + double g; 1.4037 + 1.4038 + if (png_ptr->screen_gamma > .000001) 1.4039 + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 1.4040 + else 1.4041 + g = 1.0; 1.4042 + 1.4043 + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, 1.4044 + (png_uint_32)256); 1.4045 + 1.4046 + for (i = 0; i < 256; i++) 1.4047 + { 1.4048 + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, 1.4049 + g) * 255.0 + .5); 1.4050 + } 1.4051 + 1.4052 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 1.4053 + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.4054 + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) 1.4055 + { 1.4056 + 1.4057 + g = 1.0 / (png_ptr->gamma); 1.4058 + 1.4059 + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, 1.4060 + (png_uint_32)256); 1.4061 + 1.4062 + for (i = 0; i < 256; i++) 1.4063 + { 1.4064 + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, 1.4065 + g) * 255.0 + .5); 1.4066 + } 1.4067 + 1.4068 + 1.4069 + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, 1.4070 + (png_uint_32)256); 1.4071 + 1.4072 + if (png_ptr->screen_gamma > 0.000001) 1.4073 + g = 1.0 / png_ptr->screen_gamma; 1.4074 + else 1.4075 + g = png_ptr->gamma; /* probably doing rgb_to_gray */ 1.4076 + 1.4077 + for (i = 0; i < 256; i++) 1.4078 + { 1.4079 + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, 1.4080 + g) * 255.0 + .5); 1.4081 + 1.4082 + } 1.4083 + } 1.4084 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 1.4085 + } 1.4086 + else 1.4087 + { 1.4088 + double g; 1.4089 + int i, j, shift, num; 1.4090 + int sig_bit; 1.4091 + png_uint_32 ig; 1.4092 + 1.4093 + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 1.4094 + { 1.4095 + sig_bit = (int)png_ptr->sig_bit.red; 1.4096 + if ((int)png_ptr->sig_bit.green > sig_bit) 1.4097 + sig_bit = png_ptr->sig_bit.green; 1.4098 + if ((int)png_ptr->sig_bit.blue > sig_bit) 1.4099 + sig_bit = png_ptr->sig_bit.blue; 1.4100 + } 1.4101 + else 1.4102 + { 1.4103 + sig_bit = (int)png_ptr->sig_bit.gray; 1.4104 + } 1.4105 + 1.4106 + if (sig_bit > 0) 1.4107 + shift = 16 - sig_bit; 1.4108 + else 1.4109 + shift = 0; 1.4110 + 1.4111 + if (png_ptr->transformations & PNG_16_TO_8) 1.4112 + { 1.4113 + if (shift < (16 - PNG_MAX_GAMMA_8)) 1.4114 + shift = (16 - PNG_MAX_GAMMA_8); 1.4115 + } 1.4116 + 1.4117 + if (shift > 8) 1.4118 + shift = 8; 1.4119 + if (shift < 0) 1.4120 + shift = 0; 1.4121 + 1.4122 + png_ptr->gamma_shift = (png_byte)shift; 1.4123 + 1.4124 + num = (1 << (8 - shift)); 1.4125 + 1.4126 + if (png_ptr->screen_gamma > .000001) 1.4127 + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 1.4128 + else 1.4129 + g = 1.0; 1.4130 + 1.4131 + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, 1.4132 + (png_uint_32)(num * png_sizeof(png_uint_16p))); 1.4133 + 1.4134 + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) 1.4135 + { 1.4136 + double fin, fout; 1.4137 + png_uint_32 last, max; 1.4138 + 1.4139 + for (i = 0; i < num; i++) 1.4140 + { 1.4141 + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 1.4142 + (png_uint_32)(256 * png_sizeof(png_uint_16))); 1.4143 + } 1.4144 + 1.4145 + g = 1.0 / g; 1.4146 + last = 0; 1.4147 + for (i = 0; i < 256; i++) 1.4148 + { 1.4149 + fout = ((double)i + 0.5) / 256.0; 1.4150 + fin = pow(fout, g); 1.4151 + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); 1.4152 + while (last <= max) 1.4153 + { 1.4154 + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 1.4155 + [(int)(last >> (8 - shift))] = (png_uint_16)( 1.4156 + (png_uint_16)i | ((png_uint_16)i << 8)); 1.4157 + last++; 1.4158 + } 1.4159 + } 1.4160 + while (last < ((png_uint_32)num << 8)) 1.4161 + { 1.4162 + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 1.4163 + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; 1.4164 + last++; 1.4165 + } 1.4166 + } 1.4167 + else 1.4168 + { 1.4169 + for (i = 0; i < num; i++) 1.4170 + { 1.4171 + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 1.4172 + (png_uint_32)(256 * png_sizeof(png_uint_16))); 1.4173 + 1.4174 + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); 1.4175 + for (j = 0; j < 256; j++) 1.4176 + { 1.4177 + png_ptr->gamma_16_table[i][j] = 1.4178 + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 1.4179 + 65535.0, g) * 65535.0 + .5); 1.4180 + } 1.4181 + } 1.4182 + } 1.4183 + 1.4184 +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 1.4185 + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 1.4186 + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) 1.4187 + { 1.4188 + 1.4189 + g = 1.0 / (png_ptr->gamma); 1.4190 + 1.4191 + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, 1.4192 + (png_uint_32)(num * png_sizeof(png_uint_16p ))); 1.4193 + 1.4194 + for (i = 0; i < num; i++) 1.4195 + { 1.4196 + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, 1.4197 + (png_uint_32)(256 * png_sizeof(png_uint_16))); 1.4198 + 1.4199 + ig = (((png_uint_32)i * 1.4200 + (png_uint_32)png_gamma_shift[shift]) >> 4); 1.4201 + for (j = 0; j < 256; j++) 1.4202 + { 1.4203 + png_ptr->gamma_16_to_1[i][j] = 1.4204 + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 1.4205 + 65535.0, g) * 65535.0 + .5); 1.4206 + } 1.4207 + } 1.4208 + 1.4209 + if (png_ptr->screen_gamma > 0.000001) 1.4210 + g = 1.0 / png_ptr->screen_gamma; 1.4211 + else 1.4212 + g = png_ptr->gamma; /* probably doing rgb_to_gray */ 1.4213 + 1.4214 + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, 1.4215 + (png_uint_32)(num * png_sizeof(png_uint_16p))); 1.4216 + 1.4217 + for (i = 0; i < num; i++) 1.4218 + { 1.4219 + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, 1.4220 + (png_uint_32)(256 * png_sizeof(png_uint_16))); 1.4221 + 1.4222 + ig = (((png_uint_32)i * 1.4223 + (png_uint_32)png_gamma_shift[shift]) >> 4); 1.4224 + for (j = 0; j < 256; j++) 1.4225 + { 1.4226 + png_ptr->gamma_16_from_1[i][j] = 1.4227 + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 1.4228 + 65535.0, g) * 65535.0 + .5); 1.4229 + } 1.4230 + } 1.4231 + } 1.4232 +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 1.4233 + } 1.4234 +} 1.4235 +#endif 1.4236 +/* To do: install integer version of png_build_gamma_table here */ 1.4237 +#endif 1.4238 + 1.4239 +#if defined(PNG_MNG_FEATURES_SUPPORTED) 1.4240 +/* undoes intrapixel differencing */ 1.4241 +void /* PRIVATE */ 1.4242 +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) 1.4243 +{ 1.4244 + png_debug(1, "in png_do_read_intrapixel\n"); 1.4245 + if ( 1.4246 +#if defined(PNG_USELESS_TESTS_SUPPORTED) 1.4247 + row != NULL && row_info != NULL && 1.4248 +#endif 1.4249 + (row_info->color_type & PNG_COLOR_MASK_COLOR)) 1.4250 + { 1.4251 + int bytes_per_pixel; 1.4252 + png_uint_32 row_width = row_info->width; 1.4253 + if (row_info->bit_depth == 8) 1.4254 + { 1.4255 + png_bytep rp; 1.4256 + png_uint_32 i; 1.4257 + 1.4258 + if (row_info->color_type == PNG_COLOR_TYPE_RGB) 1.4259 + bytes_per_pixel = 3; 1.4260 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.4261 + bytes_per_pixel = 4; 1.4262 + else 1.4263 + return; 1.4264 + 1.4265 + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 1.4266 + { 1.4267 + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); 1.4268 + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); 1.4269 + } 1.4270 + } 1.4271 + else if (row_info->bit_depth == 16) 1.4272 + { 1.4273 + png_bytep rp; 1.4274 + png_uint_32 i; 1.4275 + 1.4276 + if (row_info->color_type == PNG_COLOR_TYPE_RGB) 1.4277 + bytes_per_pixel = 6; 1.4278 + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1.4279 + bytes_per_pixel = 8; 1.4280 + else 1.4281 + return; 1.4282 + 1.4283 + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 1.4284 + { 1.4285 + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 1.4286 + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 1.4287 + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 1.4288 + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); 1.4289 + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); 1.4290 + *(rp ) = (png_byte)((red >> 8) & 0xff); 1.4291 + *(rp+1) = (png_byte)(red & 0xff); 1.4292 + *(rp+4) = (png_byte)((blue >> 8) & 0xff); 1.4293 + *(rp+5) = (png_byte)(blue & 0xff); 1.4294 + } 1.4295 + } 1.4296 + } 1.4297 +} 1.4298 +#endif /* PNG_MNG_FEATURES_SUPPORTED */ 1.4299 +#endif /* PNG_READ_SUPPORTED */