Mercurial > fife-parpg
comparison ext/libpng-1.2.29/pngrtran.c @ 89:fa33cda75471
* Reverting back to 2543 as requested by sleek
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sat, 19 Jul 2008 11:38:52 +0000 |
parents | 4a0efb7baf70 |
children |
comparison
equal
deleted
inserted
replaced
88:1c2842ebe393 | 89:fa33cda75471 |
---|---|
1 | |
2 /* pngrtran.c - transforms the data in a row for PNG readers | |
3 * | |
4 * Last changed in libpng 1.2.27 [April 29, 2008] | |
5 * For conditions of distribution and use, see copyright notice in png.h | |
6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson | |
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |
9 * | |
10 * This file contains functions optionally called by an application | |
11 * in order to tell libpng how to handle data when reading a PNG. | |
12 * Transformations that are used in both reading and writing are | |
13 * in pngtrans.c. | |
14 */ | |
15 | |
16 #define PNG_INTERNAL | |
17 #include "png.h" | |
18 | |
19 #if defined(PNG_READ_SUPPORTED) | |
20 | |
21 /* Set the action on getting a CRC error for an ancillary or critical chunk. */ | |
22 void PNGAPI | |
23 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) | |
24 { | |
25 png_debug(1, "in png_set_crc_action\n"); | |
26 /* Tell libpng how we react to CRC errors in critical chunks */ | |
27 if(png_ptr == NULL) return; | |
28 switch (crit_action) | |
29 { | |
30 case PNG_CRC_NO_CHANGE: /* leave setting as is */ | |
31 break; | |
32 case PNG_CRC_WARN_USE: /* warn/use data */ | |
33 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; | |
34 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; | |
35 break; | |
36 case PNG_CRC_QUIET_USE: /* quiet/use data */ | |
37 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; | |
38 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | | |
39 PNG_FLAG_CRC_CRITICAL_IGNORE; | |
40 break; | |
41 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ | |
42 png_warning(png_ptr, "Can't discard critical data on CRC error."); | |
43 case PNG_CRC_ERROR_QUIT: /* error/quit */ | |
44 case PNG_CRC_DEFAULT: | |
45 default: | |
46 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; | |
47 break; | |
48 } | |
49 | |
50 switch (ancil_action) | |
51 { | |
52 case PNG_CRC_NO_CHANGE: /* leave setting as is */ | |
53 break; | |
54 case PNG_CRC_WARN_USE: /* warn/use data */ | |
55 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; | |
56 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; | |
57 break; | |
58 case PNG_CRC_QUIET_USE: /* quiet/use data */ | |
59 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; | |
60 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | | |
61 PNG_FLAG_CRC_ANCILLARY_NOWARN; | |
62 break; | |
63 case PNG_CRC_ERROR_QUIT: /* error/quit */ | |
64 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; | |
65 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; | |
66 break; | |
67 case PNG_CRC_WARN_DISCARD: /* warn/discard data */ | |
68 case PNG_CRC_DEFAULT: | |
69 default: | |
70 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; | |
71 break; | |
72 } | |
73 } | |
74 | |
75 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ | |
76 defined(PNG_FLOATING_POINT_SUPPORTED) | |
77 /* handle alpha and tRNS via a background color */ | |
78 void PNGAPI | |
79 png_set_background(png_structp png_ptr, | |
80 png_color_16p background_color, int background_gamma_code, | |
81 int need_expand, double background_gamma) | |
82 { | |
83 png_debug(1, "in png_set_background\n"); | |
84 if(png_ptr == NULL) return; | |
85 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) | |
86 { | |
87 png_warning(png_ptr, "Application must supply a known background gamma"); | |
88 return; | |
89 } | |
90 | |
91 png_ptr->transformations |= PNG_BACKGROUND; | |
92 png_memcpy(&(png_ptr->background), background_color, | |
93 png_sizeof(png_color_16)); | |
94 png_ptr->background_gamma = (float)background_gamma; | |
95 png_ptr->background_gamma_type = (png_byte)(background_gamma_code); | |
96 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); | |
97 } | |
98 #endif | |
99 | |
100 #if defined(PNG_READ_16_TO_8_SUPPORTED) | |
101 /* strip 16 bit depth files to 8 bit depth */ | |
102 void PNGAPI | |
103 png_set_strip_16(png_structp png_ptr) | |
104 { | |
105 png_debug(1, "in png_set_strip_16\n"); | |
106 if(png_ptr == NULL) return; | |
107 png_ptr->transformations |= PNG_16_TO_8; | |
108 } | |
109 #endif | |
110 | |
111 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) | |
112 void PNGAPI | |
113 png_set_strip_alpha(png_structp png_ptr) | |
114 { | |
115 png_debug(1, "in png_set_strip_alpha\n"); | |
116 if(png_ptr == NULL) return; | |
117 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; | |
118 } | |
119 #endif | |
120 | |
121 #if defined(PNG_READ_DITHER_SUPPORTED) | |
122 /* Dither file to 8 bit. Supply a palette, the current number | |
123 * of elements in the palette, the maximum number of elements | |
124 * allowed, and a histogram if possible. If the current number | |
125 * of colors is greater then the maximum number, the palette will be | |
126 * modified to fit in the maximum number. "full_dither" indicates | |
127 * whether we need a dithering cube set up for RGB images, or if we | |
128 * simply are reducing the number of colors in a paletted image. | |
129 */ | |
130 | |
131 typedef struct png_dsort_struct | |
132 { | |
133 struct png_dsort_struct FAR * next; | |
134 png_byte left; | |
135 png_byte right; | |
136 } png_dsort; | |
137 typedef png_dsort FAR * png_dsortp; | |
138 typedef png_dsort FAR * FAR * png_dsortpp; | |
139 | |
140 void PNGAPI | |
141 png_set_dither(png_structp png_ptr, png_colorp palette, | |
142 int num_palette, int maximum_colors, png_uint_16p histogram, | |
143 int full_dither) | |
144 { | |
145 png_debug(1, "in png_set_dither\n"); | |
146 if(png_ptr == NULL) return; | |
147 png_ptr->transformations |= PNG_DITHER; | |
148 | |
149 if (!full_dither) | |
150 { | |
151 int i; | |
152 | |
153 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, | |
154 (png_uint_32)(num_palette * png_sizeof (png_byte))); | |
155 for (i = 0; i < num_palette; i++) | |
156 png_ptr->dither_index[i] = (png_byte)i; | |
157 } | |
158 | |
159 if (num_palette > maximum_colors) | |
160 { | |
161 if (histogram != NULL) | |
162 { | |
163 /* This is easy enough, just throw out the least used colors. | |
164 Perhaps not the best solution, but good enough. */ | |
165 | |
166 int i; | |
167 | |
168 /* initialize an array to sort colors */ | |
169 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, | |
170 (png_uint_32)(num_palette * png_sizeof (png_byte))); | |
171 | |
172 /* initialize the dither_sort array */ | |
173 for (i = 0; i < num_palette; i++) | |
174 png_ptr->dither_sort[i] = (png_byte)i; | |
175 | |
176 /* Find the least used palette entries by starting a | |
177 bubble sort, and running it until we have sorted | |
178 out enough colors. Note that we don't care about | |
179 sorting all the colors, just finding which are | |
180 least used. */ | |
181 | |
182 for (i = num_palette - 1; i >= maximum_colors; i--) | |
183 { | |
184 int done; /* to stop early if the list is pre-sorted */ | |
185 int j; | |
186 | |
187 done = 1; | |
188 for (j = 0; j < i; j++) | |
189 { | |
190 if (histogram[png_ptr->dither_sort[j]] | |
191 < histogram[png_ptr->dither_sort[j + 1]]) | |
192 { | |
193 png_byte t; | |
194 | |
195 t = png_ptr->dither_sort[j]; | |
196 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; | |
197 png_ptr->dither_sort[j + 1] = t; | |
198 done = 0; | |
199 } | |
200 } | |
201 if (done) | |
202 break; | |
203 } | |
204 | |
205 /* swap the palette around, and set up a table, if necessary */ | |
206 if (full_dither) | |
207 { | |
208 int j = num_palette; | |
209 | |
210 /* put all the useful colors within the max, but don't | |
211 move the others */ | |
212 for (i = 0; i < maximum_colors; i++) | |
213 { | |
214 if ((int)png_ptr->dither_sort[i] >= maximum_colors) | |
215 { | |
216 do | |
217 j--; | |
218 while ((int)png_ptr->dither_sort[j] >= maximum_colors); | |
219 palette[i] = palette[j]; | |
220 } | |
221 } | |
222 } | |
223 else | |
224 { | |
225 int j = num_palette; | |
226 | |
227 /* move all the used colors inside the max limit, and | |
228 develop a translation table */ | |
229 for (i = 0; i < maximum_colors; i++) | |
230 { | |
231 /* only move the colors we need to */ | |
232 if ((int)png_ptr->dither_sort[i] >= maximum_colors) | |
233 { | |
234 png_color tmp_color; | |
235 | |
236 do | |
237 j--; | |
238 while ((int)png_ptr->dither_sort[j] >= maximum_colors); | |
239 | |
240 tmp_color = palette[j]; | |
241 palette[j] = palette[i]; | |
242 palette[i] = tmp_color; | |
243 /* indicate where the color went */ | |
244 png_ptr->dither_index[j] = (png_byte)i; | |
245 png_ptr->dither_index[i] = (png_byte)j; | |
246 } | |
247 } | |
248 | |
249 /* find closest color for those colors we are not using */ | |
250 for (i = 0; i < num_palette; i++) | |
251 { | |
252 if ((int)png_ptr->dither_index[i] >= maximum_colors) | |
253 { | |
254 int min_d, k, min_k, d_index; | |
255 | |
256 /* find the closest color to one we threw out */ | |
257 d_index = png_ptr->dither_index[i]; | |
258 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); | |
259 for (k = 1, min_k = 0; k < maximum_colors; k++) | |
260 { | |
261 int d; | |
262 | |
263 d = PNG_COLOR_DIST(palette[d_index], palette[k]); | |
264 | |
265 if (d < min_d) | |
266 { | |
267 min_d = d; | |
268 min_k = k; | |
269 } | |
270 } | |
271 /* point to closest color */ | |
272 png_ptr->dither_index[i] = (png_byte)min_k; | |
273 } | |
274 } | |
275 } | |
276 png_free(png_ptr, png_ptr->dither_sort); | |
277 png_ptr->dither_sort=NULL; | |
278 } | |
279 else | |
280 { | |
281 /* This is much harder to do simply (and quickly). Perhaps | |
282 we need to go through a median cut routine, but those | |
283 don't always behave themselves with only a few colors | |
284 as input. So we will just find the closest two colors, | |
285 and throw out one of them (chosen somewhat randomly). | |
286 [We don't understand this at all, so if someone wants to | |
287 work on improving it, be our guest - AED, GRP] | |
288 */ | |
289 int i; | |
290 int max_d; | |
291 int num_new_palette; | |
292 png_dsortp t; | |
293 png_dsortpp hash; | |
294 | |
295 t=NULL; | |
296 | |
297 /* initialize palette index arrays */ | |
298 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, | |
299 (png_uint_32)(num_palette * png_sizeof (png_byte))); | |
300 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, | |
301 (png_uint_32)(num_palette * png_sizeof (png_byte))); | |
302 | |
303 /* initialize the sort array */ | |
304 for (i = 0; i < num_palette; i++) | |
305 { | |
306 png_ptr->index_to_palette[i] = (png_byte)i; | |
307 png_ptr->palette_to_index[i] = (png_byte)i; | |
308 } | |
309 | |
310 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * | |
311 png_sizeof (png_dsortp))); | |
312 for (i = 0; i < 769; i++) | |
313 hash[i] = NULL; | |
314 /* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ | |
315 | |
316 num_new_palette = num_palette; | |
317 | |
318 /* initial wild guess at how far apart the farthest pixel | |
319 pair we will be eliminating will be. Larger | |
320 numbers mean more areas will be allocated, Smaller | |
321 numbers run the risk of not saving enough data, and | |
322 having to do this all over again. | |
323 | |
324 I have not done extensive checking on this number. | |
325 */ | |
326 max_d = 96; | |
327 | |
328 while (num_new_palette > maximum_colors) | |
329 { | |
330 for (i = 0; i < num_new_palette - 1; i++) | |
331 { | |
332 int j; | |
333 | |
334 for (j = i + 1; j < num_new_palette; j++) | |
335 { | |
336 int d; | |
337 | |
338 d = PNG_COLOR_DIST(palette[i], palette[j]); | |
339 | |
340 if (d <= max_d) | |
341 { | |
342 | |
343 t = (png_dsortp)png_malloc_warn(png_ptr, | |
344 (png_uint_32)(png_sizeof(png_dsort))); | |
345 if (t == NULL) | |
346 break; | |
347 t->next = hash[d]; | |
348 t->left = (png_byte)i; | |
349 t->right = (png_byte)j; | |
350 hash[d] = t; | |
351 } | |
352 } | |
353 if (t == NULL) | |
354 break; | |
355 } | |
356 | |
357 if (t != NULL) | |
358 for (i = 0; i <= max_d; i++) | |
359 { | |
360 if (hash[i] != NULL) | |
361 { | |
362 png_dsortp p; | |
363 | |
364 for (p = hash[i]; p; p = p->next) | |
365 { | |
366 if ((int)png_ptr->index_to_palette[p->left] | |
367 < num_new_palette && | |
368 (int)png_ptr->index_to_palette[p->right] | |
369 < num_new_palette) | |
370 { | |
371 int j, next_j; | |
372 | |
373 if (num_new_palette & 0x01) | |
374 { | |
375 j = p->left; | |
376 next_j = p->right; | |
377 } | |
378 else | |
379 { | |
380 j = p->right; | |
381 next_j = p->left; | |
382 } | |
383 | |
384 num_new_palette--; | |
385 palette[png_ptr->index_to_palette[j]] | |
386 = palette[num_new_palette]; | |
387 if (!full_dither) | |
388 { | |
389 int k; | |
390 | |
391 for (k = 0; k < num_palette; k++) | |
392 { | |
393 if (png_ptr->dither_index[k] == | |
394 png_ptr->index_to_palette[j]) | |
395 png_ptr->dither_index[k] = | |
396 png_ptr->index_to_palette[next_j]; | |
397 if ((int)png_ptr->dither_index[k] == | |
398 num_new_palette) | |
399 png_ptr->dither_index[k] = | |
400 png_ptr->index_to_palette[j]; | |
401 } | |
402 } | |
403 | |
404 png_ptr->index_to_palette[png_ptr->palette_to_index | |
405 [num_new_palette]] = png_ptr->index_to_palette[j]; | |
406 png_ptr->palette_to_index[png_ptr->index_to_palette[j]] | |
407 = png_ptr->palette_to_index[num_new_palette]; | |
408 | |
409 png_ptr->index_to_palette[j] = (png_byte)num_new_palette; | |
410 png_ptr->palette_to_index[num_new_palette] = (png_byte)j; | |
411 } | |
412 if (num_new_palette <= maximum_colors) | |
413 break; | |
414 } | |
415 if (num_new_palette <= maximum_colors) | |
416 break; | |
417 } | |
418 } | |
419 | |
420 for (i = 0; i < 769; i++) | |
421 { | |
422 if (hash[i] != NULL) | |
423 { | |
424 png_dsortp p = hash[i]; | |
425 while (p) | |
426 { | |
427 t = p->next; | |
428 png_free(png_ptr, p); | |
429 p = t; | |
430 } | |
431 } | |
432 hash[i] = 0; | |
433 } | |
434 max_d += 96; | |
435 } | |
436 png_free(png_ptr, hash); | |
437 png_free(png_ptr, png_ptr->palette_to_index); | |
438 png_free(png_ptr, png_ptr->index_to_palette); | |
439 png_ptr->palette_to_index=NULL; | |
440 png_ptr->index_to_palette=NULL; | |
441 } | |
442 num_palette = maximum_colors; | |
443 } | |
444 if (png_ptr->palette == NULL) | |
445 { | |
446 png_ptr->palette = palette; | |
447 } | |
448 png_ptr->num_palette = (png_uint_16)num_palette; | |
449 | |
450 if (full_dither) | |
451 { | |
452 int i; | |
453 png_bytep distance; | |
454 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + | |
455 PNG_DITHER_BLUE_BITS; | |
456 int num_red = (1 << PNG_DITHER_RED_BITS); | |
457 int num_green = (1 << PNG_DITHER_GREEN_BITS); | |
458 int num_blue = (1 << PNG_DITHER_BLUE_BITS); | |
459 png_size_t num_entries = ((png_size_t)1 << total_bits); | |
460 | |
461 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, | |
462 (png_uint_32)(num_entries * png_sizeof (png_byte))); | |
463 | |
464 png_memset(png_ptr->palette_lookup, 0, num_entries * | |
465 png_sizeof (png_byte)); | |
466 | |
467 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * | |
468 png_sizeof(png_byte))); | |
469 | |
470 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); | |
471 | |
472 for (i = 0; i < num_palette; i++) | |
473 { | |
474 int ir, ig, ib; | |
475 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); | |
476 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); | |
477 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); | |
478 | |
479 for (ir = 0; ir < num_red; ir++) | |
480 { | |
481 /* int dr = abs(ir - r); */ | |
482 int dr = ((ir > r) ? ir - r : r - ir); | |
483 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); | |
484 | |
485 for (ig = 0; ig < num_green; ig++) | |
486 { | |
487 /* int dg = abs(ig - g); */ | |
488 int dg = ((ig > g) ? ig - g : g - ig); | |
489 int dt = dr + dg; | |
490 int dm = ((dr > dg) ? dr : dg); | |
491 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); | |
492 | |
493 for (ib = 0; ib < num_blue; ib++) | |
494 { | |
495 int d_index = index_g | ib; | |
496 /* int db = abs(ib - b); */ | |
497 int db = ((ib > b) ? ib - b : b - ib); | |
498 int dmax = ((dm > db) ? dm : db); | |
499 int d = dmax + dt + db; | |
500 | |
501 if (d < (int)distance[d_index]) | |
502 { | |
503 distance[d_index] = (png_byte)d; | |
504 png_ptr->palette_lookup[d_index] = (png_byte)i; | |
505 } | |
506 } | |
507 } | |
508 } | |
509 } | |
510 | |
511 png_free(png_ptr, distance); | |
512 } | |
513 } | |
514 #endif | |
515 | |
516 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) | |
517 /* Transform the image from the file_gamma to the screen_gamma. We | |
518 * only do transformations on images where the file_gamma and screen_gamma | |
519 * are not close reciprocals, otherwise it slows things down slightly, and | |
520 * also needlessly introduces small errors. | |
521 * | |
522 * We will turn off gamma transformation later if no semitransparent entries | |
523 * are present in the tRNS array for palette images. We can't do it here | |
524 * because we don't necessarily have the tRNS chunk yet. | |
525 */ | |
526 void PNGAPI | |
527 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) | |
528 { | |
529 png_debug(1, "in png_set_gamma\n"); | |
530 if(png_ptr == NULL) return; | |
531 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || | |
532 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || | |
533 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) | |
534 png_ptr->transformations |= PNG_GAMMA; | |
535 png_ptr->gamma = (float)file_gamma; | |
536 png_ptr->screen_gamma = (float)scrn_gamma; | |
537 } | |
538 #endif | |
539 | |
540 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
541 /* Expand paletted images to RGB, expand grayscale images of | |
542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks | |
543 * to alpha channels. | |
544 */ | |
545 void PNGAPI | |
546 png_set_expand(png_structp png_ptr) | |
547 { | |
548 png_debug(1, "in png_set_expand\n"); | |
549 if(png_ptr == NULL) return; | |
550 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); | |
551 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
552 } | |
553 | |
554 /* GRR 19990627: the following three functions currently are identical | |
555 * to png_set_expand(). However, it is entirely reasonable that someone | |
556 * might wish to expand an indexed image to RGB but *not* expand a single, | |
557 * fully transparent palette entry to a full alpha channel--perhaps instead | |
558 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace | |
559 * the transparent color with a particular RGB value, or drop tRNS entirely. | |
560 * IOW, a future version of the library may make the transformations flag | |
561 * a bit more fine-grained, with separate bits for each of these three | |
562 * functions. | |
563 * | |
564 * More to the point, these functions make it obvious what libpng will be | |
565 * doing, whereas "expand" can (and does) mean any number of things. | |
566 * | |
567 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified | |
568 * to expand only the sample depth but not to expand the tRNS to alpha. | |
569 */ | |
570 | |
571 /* Expand paletted images to RGB. */ | |
572 void PNGAPI | |
573 png_set_palette_to_rgb(png_structp png_ptr) | |
574 { | |
575 png_debug(1, "in png_set_palette_to_rgb\n"); | |
576 if(png_ptr == NULL) return; | |
577 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); | |
578 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
579 } | |
580 | |
581 #if !defined(PNG_1_0_X) | |
582 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ | |
583 void PNGAPI | |
584 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) | |
585 { | |
586 png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n"); | |
587 if(png_ptr == NULL) return; | |
588 png_ptr->transformations |= PNG_EXPAND; | |
589 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
590 } | |
591 #endif | |
592 | |
593 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) | |
594 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ | |
595 /* Deprecated as of libpng-1.2.9 */ | |
596 void PNGAPI | |
597 png_set_gray_1_2_4_to_8(png_structp png_ptr) | |
598 { | |
599 png_debug(1, "in png_set_gray_1_2_4_to_8\n"); | |
600 if(png_ptr == NULL) return; | |
601 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); | |
602 } | |
603 #endif | |
604 | |
605 | |
606 /* Expand tRNS chunks to alpha channels. */ | |
607 void PNGAPI | |
608 png_set_tRNS_to_alpha(png_structp png_ptr) | |
609 { | |
610 png_debug(1, "in png_set_tRNS_to_alpha\n"); | |
611 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); | |
612 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
613 } | |
614 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ | |
615 | |
616 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
617 void PNGAPI | |
618 png_set_gray_to_rgb(png_structp png_ptr) | |
619 { | |
620 png_debug(1, "in png_set_gray_to_rgb\n"); | |
621 png_ptr->transformations |= PNG_GRAY_TO_RGB; | |
622 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
623 } | |
624 #endif | |
625 | |
626 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
627 #if defined(PNG_FLOATING_POINT_SUPPORTED) | |
628 /* Convert a RGB image to a grayscale of the same width. This allows us, | |
629 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. | |
630 */ | |
631 | |
632 void PNGAPI | |
633 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, | |
634 double green) | |
635 { | |
636 int red_fixed = (int)((float)red*100000.0 + 0.5); | |
637 int green_fixed = (int)((float)green*100000.0 + 0.5); | |
638 if(png_ptr == NULL) return; | |
639 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); | |
640 } | |
641 #endif | |
642 | |
643 void PNGAPI | |
644 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, | |
645 png_fixed_point red, png_fixed_point green) | |
646 { | |
647 png_debug(1, "in png_set_rgb_to_gray\n"); | |
648 if(png_ptr == NULL) return; | |
649 switch(error_action) | |
650 { | |
651 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; | |
652 break; | |
653 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; | |
654 break; | |
655 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; | |
656 } | |
657 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
658 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
659 png_ptr->transformations |= PNG_EXPAND; | |
660 #else | |
661 { | |
662 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); | |
663 png_ptr->transformations &= ~PNG_RGB_TO_GRAY; | |
664 } | |
665 #endif | |
666 { | |
667 png_uint_16 red_int, green_int; | |
668 if(red < 0 || green < 0) | |
669 { | |
670 red_int = 6968; /* .212671 * 32768 + .5 */ | |
671 green_int = 23434; /* .715160 * 32768 + .5 */ | |
672 } | |
673 else if(red + green < 100000L) | |
674 { | |
675 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); | |
676 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); | |
677 } | |
678 else | |
679 { | |
680 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); | |
681 red_int = 6968; | |
682 green_int = 23434; | |
683 } | |
684 png_ptr->rgb_to_gray_red_coeff = red_int; | |
685 png_ptr->rgb_to_gray_green_coeff = green_int; | |
686 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); | |
687 } | |
688 } | |
689 #endif | |
690 | |
691 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ | |
692 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ | |
693 defined(PNG_LEGACY_SUPPORTED) | |
694 void PNGAPI | |
695 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr | |
696 read_user_transform_fn) | |
697 { | |
698 png_debug(1, "in png_set_read_user_transform_fn\n"); | |
699 if(png_ptr == NULL) return; | |
700 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) | |
701 png_ptr->transformations |= PNG_USER_TRANSFORM; | |
702 png_ptr->read_user_transform_fn = read_user_transform_fn; | |
703 #endif | |
704 #ifdef PNG_LEGACY_SUPPORTED | |
705 if(read_user_transform_fn) | |
706 png_warning(png_ptr, | |
707 "This version of libpng does not support user transforms"); | |
708 #endif | |
709 } | |
710 #endif | |
711 | |
712 /* Initialize everything needed for the read. This includes modifying | |
713 * the palette. | |
714 */ | |
715 void /* PRIVATE */ | |
716 png_init_read_transformations(png_structp png_ptr) | |
717 { | |
718 png_debug(1, "in png_init_read_transformations\n"); | |
719 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
720 if(png_ptr != NULL) | |
721 #endif | |
722 { | |
723 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ | |
724 || defined(PNG_READ_GAMMA_SUPPORTED) | |
725 int color_type = png_ptr->color_type; | |
726 #endif | |
727 | |
728 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) | |
729 | |
730 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
731 /* Detect gray background and attempt to enable optimization | |
732 * for gray --> RGB case */ | |
733 /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or | |
734 * RGB_ALPHA (in which case need_expand is superfluous anyway), the | |
735 * background color might actually be gray yet not be flagged as such. | |
736 * This is not a problem for the current code, which uses | |
737 * PNG_BACKGROUND_IS_GRAY only to decide when to do the | |
738 * png_do_gray_to_rgb() transformation. | |
739 */ | |
740 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && | |
741 !(color_type & PNG_COLOR_MASK_COLOR)) | |
742 { | |
743 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; | |
744 } else if ((png_ptr->transformations & PNG_BACKGROUND) && | |
745 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && | |
746 (png_ptr->transformations & PNG_GRAY_TO_RGB) && | |
747 png_ptr->background.red == png_ptr->background.green && | |
748 png_ptr->background.red == png_ptr->background.blue) | |
749 { | |
750 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; | |
751 png_ptr->background.gray = png_ptr->background.red; | |
752 } | |
753 #endif | |
754 | |
755 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && | |
756 (png_ptr->transformations & PNG_EXPAND)) | |
757 { | |
758 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ | |
759 { | |
760 /* expand background and tRNS chunks */ | |
761 switch (png_ptr->bit_depth) | |
762 { | |
763 case 1: | |
764 png_ptr->background.gray *= (png_uint_16)0xff; | |
765 png_ptr->background.red = png_ptr->background.green | |
766 = png_ptr->background.blue = png_ptr->background.gray; | |
767 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) | |
768 { | |
769 png_ptr->trans_values.gray *= (png_uint_16)0xff; | |
770 png_ptr->trans_values.red = png_ptr->trans_values.green | |
771 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; | |
772 } | |
773 break; | |
774 case 2: | |
775 png_ptr->background.gray *= (png_uint_16)0x55; | |
776 png_ptr->background.red = png_ptr->background.green | |
777 = png_ptr->background.blue = png_ptr->background.gray; | |
778 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) | |
779 { | |
780 png_ptr->trans_values.gray *= (png_uint_16)0x55; | |
781 png_ptr->trans_values.red = png_ptr->trans_values.green | |
782 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; | |
783 } | |
784 break; | |
785 case 4: | |
786 png_ptr->background.gray *= (png_uint_16)0x11; | |
787 png_ptr->background.red = png_ptr->background.green | |
788 = png_ptr->background.blue = png_ptr->background.gray; | |
789 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) | |
790 { | |
791 png_ptr->trans_values.gray *= (png_uint_16)0x11; | |
792 png_ptr->trans_values.red = png_ptr->trans_values.green | |
793 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; | |
794 } | |
795 break; | |
796 case 8: | |
797 case 16: | |
798 png_ptr->background.red = png_ptr->background.green | |
799 = png_ptr->background.blue = png_ptr->background.gray; | |
800 break; | |
801 } | |
802 } | |
803 else if (color_type == PNG_COLOR_TYPE_PALETTE) | |
804 { | |
805 png_ptr->background.red = | |
806 png_ptr->palette[png_ptr->background.index].red; | |
807 png_ptr->background.green = | |
808 png_ptr->palette[png_ptr->background.index].green; | |
809 png_ptr->background.blue = | |
810 png_ptr->palette[png_ptr->background.index].blue; | |
811 | |
812 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) | |
813 if (png_ptr->transformations & PNG_INVERT_ALPHA) | |
814 { | |
815 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
816 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) | |
817 #endif | |
818 { | |
819 /* invert the alpha channel (in tRNS) unless the pixels are | |
820 going to be expanded, in which case leave it for later */ | |
821 int i,istop; | |
822 istop=(int)png_ptr->num_trans; | |
823 for (i=0; i<istop; i++) | |
824 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); | |
825 } | |
826 } | |
827 #endif | |
828 | |
829 } | |
830 } | |
831 #endif | |
832 | |
833 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) | |
834 png_ptr->background_1 = png_ptr->background; | |
835 #endif | |
836 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) | |
837 | |
838 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) | |
839 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) | |
840 < PNG_GAMMA_THRESHOLD)) | |
841 { | |
842 int i,k; | |
843 k=0; | |
844 for (i=0; i<png_ptr->num_trans; i++) | |
845 { | |
846 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) | |
847 k=1; /* partial transparency is present */ | |
848 } | |
849 if (k == 0) | |
850 png_ptr->transformations &= ~PNG_GAMMA; | |
851 } | |
852 | |
853 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && | |
854 png_ptr->gamma != 0.0) | |
855 { | |
856 png_build_gamma_table(png_ptr); | |
857 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
858 if (png_ptr->transformations & PNG_BACKGROUND) | |
859 { | |
860 if (color_type == PNG_COLOR_TYPE_PALETTE) | |
861 { | |
862 /* could skip if no transparency and | |
863 */ | |
864 png_color back, back_1; | |
865 png_colorp palette = png_ptr->palette; | |
866 int num_palette = png_ptr->num_palette; | |
867 int i; | |
868 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) | |
869 { | |
870 back.red = png_ptr->gamma_table[png_ptr->background.red]; | |
871 back.green = png_ptr->gamma_table[png_ptr->background.green]; | |
872 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; | |
873 | |
874 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; | |
875 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; | |
876 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; | |
877 } | |
878 else | |
879 { | |
880 double g, gs; | |
881 | |
882 switch (png_ptr->background_gamma_type) | |
883 { | |
884 case PNG_BACKGROUND_GAMMA_SCREEN: | |
885 g = (png_ptr->screen_gamma); | |
886 gs = 1.0; | |
887 break; | |
888 case PNG_BACKGROUND_GAMMA_FILE: | |
889 g = 1.0 / (png_ptr->gamma); | |
890 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); | |
891 break; | |
892 case PNG_BACKGROUND_GAMMA_UNIQUE: | |
893 g = 1.0 / (png_ptr->background_gamma); | |
894 gs = 1.0 / (png_ptr->background_gamma * | |
895 png_ptr->screen_gamma); | |
896 break; | |
897 default: | |
898 g = 1.0; /* back_1 */ | |
899 gs = 1.0; /* back */ | |
900 } | |
901 | |
902 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) | |
903 { | |
904 back.red = (png_byte)png_ptr->background.red; | |
905 back.green = (png_byte)png_ptr->background.green; | |
906 back.blue = (png_byte)png_ptr->background.blue; | |
907 } | |
908 else | |
909 { | |
910 back.red = (png_byte)(pow( | |
911 (double)png_ptr->background.red/255, gs) * 255.0 + .5); | |
912 back.green = (png_byte)(pow( | |
913 (double)png_ptr->background.green/255, gs) * 255.0 + .5); | |
914 back.blue = (png_byte)(pow( | |
915 (double)png_ptr->background.blue/255, gs) * 255.0 + .5); | |
916 } | |
917 | |
918 back_1.red = (png_byte)(pow( | |
919 (double)png_ptr->background.red/255, g) * 255.0 + .5); | |
920 back_1.green = (png_byte)(pow( | |
921 (double)png_ptr->background.green/255, g) * 255.0 + .5); | |
922 back_1.blue = (png_byte)(pow( | |
923 (double)png_ptr->background.blue/255, g) * 255.0 + .5); | |
924 } | |
925 for (i = 0; i < num_palette; i++) | |
926 { | |
927 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) | |
928 { | |
929 if (png_ptr->trans[i] == 0) | |
930 { | |
931 palette[i] = back; | |
932 } | |
933 else /* if (png_ptr->trans[i] != 0xff) */ | |
934 { | |
935 png_byte v, w; | |
936 | |
937 v = png_ptr->gamma_to_1[palette[i].red]; | |
938 png_composite(w, v, png_ptr->trans[i], back_1.red); | |
939 palette[i].red = png_ptr->gamma_from_1[w]; | |
940 | |
941 v = png_ptr->gamma_to_1[palette[i].green]; | |
942 png_composite(w, v, png_ptr->trans[i], back_1.green); | |
943 palette[i].green = png_ptr->gamma_from_1[w]; | |
944 | |
945 v = png_ptr->gamma_to_1[palette[i].blue]; | |
946 png_composite(w, v, png_ptr->trans[i], back_1.blue); | |
947 palette[i].blue = png_ptr->gamma_from_1[w]; | |
948 } | |
949 } | |
950 else | |
951 { | |
952 palette[i].red = png_ptr->gamma_table[palette[i].red]; | |
953 palette[i].green = png_ptr->gamma_table[palette[i].green]; | |
954 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; | |
955 } | |
956 } | |
957 /* Prevent the transformations being done again, and make sure | |
958 * that the now spurious alpha channel is stripped - the code | |
959 * has just reduced background composition and gamma correction | |
960 * to a simple alpha channel strip. | |
961 */ | |
962 png_ptr->transformations &= ~PNG_BACKGROUND; | |
963 png_ptr->transformations &= ~PNG_GAMMA; | |
964 png_ptr->transformations |= PNG_STRIP_ALPHA; | |
965 } | |
966 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ | |
967 else | |
968 /* color_type != PNG_COLOR_TYPE_PALETTE */ | |
969 { | |
970 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); | |
971 double g = 1.0; | |
972 double gs = 1.0; | |
973 | |
974 switch (png_ptr->background_gamma_type) | |
975 { | |
976 case PNG_BACKGROUND_GAMMA_SCREEN: | |
977 g = (png_ptr->screen_gamma); | |
978 gs = 1.0; | |
979 break; | |
980 case PNG_BACKGROUND_GAMMA_FILE: | |
981 g = 1.0 / (png_ptr->gamma); | |
982 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); | |
983 break; | |
984 case PNG_BACKGROUND_GAMMA_UNIQUE: | |
985 g = 1.0 / (png_ptr->background_gamma); | |
986 gs = 1.0 / (png_ptr->background_gamma * | |
987 png_ptr->screen_gamma); | |
988 break; | |
989 } | |
990 | |
991 png_ptr->background_1.gray = (png_uint_16)(pow( | |
992 (double)png_ptr->background.gray / m, g) * m + .5); | |
993 png_ptr->background.gray = (png_uint_16)(pow( | |
994 (double)png_ptr->background.gray / m, gs) * m + .5); | |
995 | |
996 if ((png_ptr->background.red != png_ptr->background.green) || | |
997 (png_ptr->background.red != png_ptr->background.blue) || | |
998 (png_ptr->background.red != png_ptr->background.gray)) | |
999 { | |
1000 /* RGB or RGBA with color background */ | |
1001 png_ptr->background_1.red = (png_uint_16)(pow( | |
1002 (double)png_ptr->background.red / m, g) * m + .5); | |
1003 png_ptr->background_1.green = (png_uint_16)(pow( | |
1004 (double)png_ptr->background.green / m, g) * m + .5); | |
1005 png_ptr->background_1.blue = (png_uint_16)(pow( | |
1006 (double)png_ptr->background.blue / m, g) * m + .5); | |
1007 png_ptr->background.red = (png_uint_16)(pow( | |
1008 (double)png_ptr->background.red / m, gs) * m + .5); | |
1009 png_ptr->background.green = (png_uint_16)(pow( | |
1010 (double)png_ptr->background.green / m, gs) * m + .5); | |
1011 png_ptr->background.blue = (png_uint_16)(pow( | |
1012 (double)png_ptr->background.blue / m, gs) * m + .5); | |
1013 } | |
1014 else | |
1015 { | |
1016 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ | |
1017 png_ptr->background_1.red = png_ptr->background_1.green | |
1018 = png_ptr->background_1.blue = png_ptr->background_1.gray; | |
1019 png_ptr->background.red = png_ptr->background.green | |
1020 = png_ptr->background.blue = png_ptr->background.gray; | |
1021 } | |
1022 } | |
1023 } | |
1024 else | |
1025 /* transformation does not include PNG_BACKGROUND */ | |
1026 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ | |
1027 if (color_type == PNG_COLOR_TYPE_PALETTE) | |
1028 { | |
1029 png_colorp palette = png_ptr->palette; | |
1030 int num_palette = png_ptr->num_palette; | |
1031 int i; | |
1032 | |
1033 for (i = 0; i < num_palette; i++) | |
1034 { | |
1035 palette[i].red = png_ptr->gamma_table[palette[i].red]; | |
1036 palette[i].green = png_ptr->gamma_table[palette[i].green]; | |
1037 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; | |
1038 } | |
1039 | |
1040 /* Done the gamma correction. */ | |
1041 png_ptr->transformations &= ~PNG_GAMMA; | |
1042 } | |
1043 } | |
1044 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1045 else | |
1046 #endif | |
1047 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ | |
1048 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1049 /* No GAMMA transformation */ | |
1050 if ((png_ptr->transformations & PNG_BACKGROUND) && | |
1051 (color_type == PNG_COLOR_TYPE_PALETTE)) | |
1052 { | |
1053 int i; | |
1054 int istop = (int)png_ptr->num_trans; | |
1055 png_color back; | |
1056 png_colorp palette = png_ptr->palette; | |
1057 | |
1058 back.red = (png_byte)png_ptr->background.red; | |
1059 back.green = (png_byte)png_ptr->background.green; | |
1060 back.blue = (png_byte)png_ptr->background.blue; | |
1061 | |
1062 for (i = 0; i < istop; i++) | |
1063 { | |
1064 if (png_ptr->trans[i] == 0) | |
1065 { | |
1066 palette[i] = back; | |
1067 } | |
1068 else if (png_ptr->trans[i] != 0xff) | |
1069 { | |
1070 /* The png_composite() macro is defined in png.h */ | |
1071 png_composite(palette[i].red, palette[i].red, | |
1072 png_ptr->trans[i], back.red); | |
1073 png_composite(palette[i].green, palette[i].green, | |
1074 png_ptr->trans[i], back.green); | |
1075 png_composite(palette[i].blue, palette[i].blue, | |
1076 png_ptr->trans[i], back.blue); | |
1077 } | |
1078 } | |
1079 | |
1080 /* Handled alpha, still need to strip the channel. */ | |
1081 png_ptr->transformations &= ~PNG_BACKGROUND; | |
1082 png_ptr->transformations |= PNG_STRIP_ALPHA; | |
1083 } | |
1084 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ | |
1085 | |
1086 #if defined(PNG_READ_SHIFT_SUPPORTED) | |
1087 if ((png_ptr->transformations & PNG_SHIFT) && | |
1088 (color_type == PNG_COLOR_TYPE_PALETTE)) | |
1089 { | |
1090 png_uint_16 i; | |
1091 png_uint_16 istop = png_ptr->num_palette; | |
1092 int sr = 8 - png_ptr->sig_bit.red; | |
1093 int sg = 8 - png_ptr->sig_bit.green; | |
1094 int sb = 8 - png_ptr->sig_bit.blue; | |
1095 | |
1096 if (sr < 0 || sr > 8) | |
1097 sr = 0; | |
1098 if (sg < 0 || sg > 8) | |
1099 sg = 0; | |
1100 if (sb < 0 || sb > 8) | |
1101 sb = 0; | |
1102 for (i = 0; i < istop; i++) | |
1103 { | |
1104 png_ptr->palette[i].red >>= sr; | |
1105 png_ptr->palette[i].green >>= sg; | |
1106 png_ptr->palette[i].blue >>= sb; | |
1107 } | |
1108 } | |
1109 #endif /* PNG_READ_SHIFT_SUPPORTED */ | |
1110 } | |
1111 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ | |
1112 && !defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1113 if(png_ptr) | |
1114 return; | |
1115 #endif | |
1116 } | |
1117 | |
1118 /* Modify the info structure to reflect the transformations. The | |
1119 * info should be updated so a PNG file could be written with it, | |
1120 * assuming the transformations result in valid PNG data. | |
1121 */ | |
1122 void /* PRIVATE */ | |
1123 png_read_transform_info(png_structp png_ptr, png_infop info_ptr) | |
1124 { | |
1125 png_debug(1, "in png_read_transform_info\n"); | |
1126 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
1127 if (png_ptr->transformations & PNG_EXPAND) | |
1128 { | |
1129 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
1130 { | |
1131 if (png_ptr->num_trans && | |
1132 (png_ptr->transformations & PNG_EXPAND_tRNS)) | |
1133 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; | |
1134 else | |
1135 info_ptr->color_type = PNG_COLOR_TYPE_RGB; | |
1136 info_ptr->bit_depth = 8; | |
1137 info_ptr->num_trans = 0; | |
1138 } | |
1139 else | |
1140 { | |
1141 if (png_ptr->num_trans) | |
1142 { | |
1143 if (png_ptr->transformations & PNG_EXPAND_tRNS) | |
1144 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; | |
1145 #if 0 /* Removed from libpng-1.2.27 */ | |
1146 else | |
1147 info_ptr->color_type |= PNG_COLOR_MASK_COLOR; | |
1148 #endif | |
1149 } | |
1150 if (info_ptr->bit_depth < 8) | |
1151 info_ptr->bit_depth = 8; | |
1152 info_ptr->num_trans = 0; | |
1153 } | |
1154 } | |
1155 #endif | |
1156 | |
1157 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1158 if (png_ptr->transformations & PNG_BACKGROUND) | |
1159 { | |
1160 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; | |
1161 info_ptr->num_trans = 0; | |
1162 info_ptr->background = png_ptr->background; | |
1163 } | |
1164 #endif | |
1165 | |
1166 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
1167 if (png_ptr->transformations & PNG_GAMMA) | |
1168 { | |
1169 #ifdef PNG_FLOATING_POINT_SUPPORTED | |
1170 info_ptr->gamma = png_ptr->gamma; | |
1171 #endif | |
1172 #ifdef PNG_FIXED_POINT_SUPPORTED | |
1173 info_ptr->int_gamma = png_ptr->int_gamma; | |
1174 #endif | |
1175 } | |
1176 #endif | |
1177 | |
1178 #if defined(PNG_READ_16_TO_8_SUPPORTED) | |
1179 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) | |
1180 info_ptr->bit_depth = 8; | |
1181 #endif | |
1182 | |
1183 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
1184 if (png_ptr->transformations & PNG_GRAY_TO_RGB) | |
1185 info_ptr->color_type |= PNG_COLOR_MASK_COLOR; | |
1186 #endif | |
1187 | |
1188 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
1189 if (png_ptr->transformations & PNG_RGB_TO_GRAY) | |
1190 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; | |
1191 #endif | |
1192 | |
1193 #if defined(PNG_READ_DITHER_SUPPORTED) | |
1194 if (png_ptr->transformations & PNG_DITHER) | |
1195 { | |
1196 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || | |
1197 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && | |
1198 png_ptr->palette_lookup && info_ptr->bit_depth == 8) | |
1199 { | |
1200 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; | |
1201 } | |
1202 } | |
1203 #endif | |
1204 | |
1205 #if defined(PNG_READ_PACK_SUPPORTED) | |
1206 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) | |
1207 info_ptr->bit_depth = 8; | |
1208 #endif | |
1209 | |
1210 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
1211 info_ptr->channels = 1; | |
1212 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) | |
1213 info_ptr->channels = 3; | |
1214 else | |
1215 info_ptr->channels = 1; | |
1216 | |
1217 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) | |
1218 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) | |
1219 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; | |
1220 #endif | |
1221 | |
1222 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) | |
1223 info_ptr->channels++; | |
1224 | |
1225 #if defined(PNG_READ_FILLER_SUPPORTED) | |
1226 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ | |
1227 if ((png_ptr->transformations & PNG_FILLER) && | |
1228 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || | |
1229 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) | |
1230 { | |
1231 info_ptr->channels++; | |
1232 /* if adding a true alpha channel not just filler */ | |
1233 #if !defined(PNG_1_0_X) | |
1234 if (png_ptr->transformations & PNG_ADD_ALPHA) | |
1235 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; | |
1236 #endif | |
1237 } | |
1238 #endif | |
1239 | |
1240 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ | |
1241 defined(PNG_READ_USER_TRANSFORM_SUPPORTED) | |
1242 if(png_ptr->transformations & PNG_USER_TRANSFORM) | |
1243 { | |
1244 if(info_ptr->bit_depth < png_ptr->user_transform_depth) | |
1245 info_ptr->bit_depth = png_ptr->user_transform_depth; | |
1246 if(info_ptr->channels < png_ptr->user_transform_channels) | |
1247 info_ptr->channels = png_ptr->user_transform_channels; | |
1248 } | |
1249 #endif | |
1250 | |
1251 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * | |
1252 info_ptr->bit_depth); | |
1253 | |
1254 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); | |
1255 | |
1256 #if !defined(PNG_READ_EXPAND_SUPPORTED) | |
1257 if(png_ptr) | |
1258 return; | |
1259 #endif | |
1260 } | |
1261 | |
1262 /* Transform the row. The order of transformations is significant, | |
1263 * and is very touchy. If you add a transformation, take care to | |
1264 * decide how it fits in with the other transformations here. | |
1265 */ | |
1266 void /* PRIVATE */ | |
1267 png_do_read_transformations(png_structp png_ptr) | |
1268 { | |
1269 png_debug(1, "in png_do_read_transformations\n"); | |
1270 if (png_ptr->row_buf == NULL) | |
1271 { | |
1272 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) | |
1273 char msg[50]; | |
1274 | |
1275 png_snprintf2(msg, 50, | |
1276 "NULL row buffer for row %ld, pass %d", png_ptr->row_number, | |
1277 png_ptr->pass); | |
1278 png_error(png_ptr, msg); | |
1279 #else | |
1280 png_error(png_ptr, "NULL row buffer"); | |
1281 #endif | |
1282 } | |
1283 #ifdef PNG_WARN_UNINITIALIZED_ROW | |
1284 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) | |
1285 /* Application has failed to call either png_read_start_image() | |
1286 * or png_read_update_info() after setting transforms that expand | |
1287 * pixels. This check added to libpng-1.2.19 */ | |
1288 #if (PNG_WARN_UNINITIALIZED_ROW==1) | |
1289 png_error(png_ptr, "Uninitialized row"); | |
1290 #else | |
1291 png_warning(png_ptr, "Uninitialized row"); | |
1292 #endif | |
1293 #endif | |
1294 | |
1295 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
1296 if (png_ptr->transformations & PNG_EXPAND) | |
1297 { | |
1298 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) | |
1299 { | |
1300 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1301 png_ptr->palette, png_ptr->trans, png_ptr->num_trans); | |
1302 } | |
1303 else | |
1304 { | |
1305 if (png_ptr->num_trans && | |
1306 (png_ptr->transformations & PNG_EXPAND_tRNS)) | |
1307 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1308 &(png_ptr->trans_values)); | |
1309 else | |
1310 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1311 NULL); | |
1312 } | |
1313 } | |
1314 #endif | |
1315 | |
1316 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) | |
1317 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) | |
1318 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1319 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); | |
1320 #endif | |
1321 | |
1322 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
1323 if (png_ptr->transformations & PNG_RGB_TO_GRAY) | |
1324 { | |
1325 int rgb_error = | |
1326 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); | |
1327 if(rgb_error) | |
1328 { | |
1329 png_ptr->rgb_to_gray_status=1; | |
1330 if((png_ptr->transformations & PNG_RGB_TO_GRAY) == | |
1331 PNG_RGB_TO_GRAY_WARN) | |
1332 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); | |
1333 if((png_ptr->transformations & PNG_RGB_TO_GRAY) == | |
1334 PNG_RGB_TO_GRAY_ERR) | |
1335 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); | |
1336 } | |
1337 } | |
1338 #endif | |
1339 | |
1340 /* | |
1341 From Andreas Dilger e-mail to png-implement, 26 March 1998: | |
1342 | |
1343 In most cases, the "simple transparency" should be done prior to doing | |
1344 gray-to-RGB, or you will have to test 3x as many bytes to check if a | |
1345 pixel is transparent. You would also need to make sure that the | |
1346 transparency information is upgraded to RGB. | |
1347 | |
1348 To summarize, the current flow is: | |
1349 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite | |
1350 with background "in place" if transparent, | |
1351 convert to RGB if necessary | |
1352 - Gray + alpha -> composite with gray background and remove alpha bytes, | |
1353 convert to RGB if necessary | |
1354 | |
1355 To support RGB backgrounds for gray images we need: | |
1356 - Gray + simple transparency -> convert to RGB + simple transparency, compare | |
1357 3 or 6 bytes and composite with background | |
1358 "in place" if transparent (3x compare/pixel | |
1359 compared to doing composite with gray bkgrnd) | |
1360 - Gray + alpha -> convert to RGB + alpha, composite with background and | |
1361 remove alpha bytes (3x float operations/pixel | |
1362 compared with composite on gray background) | |
1363 | |
1364 Greg's change will do this. The reason it wasn't done before is for | |
1365 performance, as this increases the per-pixel operations. If we would check | |
1366 in advance if the background was gray or RGB, and position the gray-to-RGB | |
1367 transform appropriately, then it would save a lot of work/time. | |
1368 */ | |
1369 | |
1370 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
1371 /* if gray -> RGB, do so now only if background is non-gray; else do later | |
1372 * for performance reasons */ | |
1373 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && | |
1374 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) | |
1375 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1376 #endif | |
1377 | |
1378 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1379 if ((png_ptr->transformations & PNG_BACKGROUND) && | |
1380 ((png_ptr->num_trans != 0 ) || | |
1381 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) | |
1382 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1383 &(png_ptr->trans_values), &(png_ptr->background) | |
1384 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
1385 , &(png_ptr->background_1), | |
1386 png_ptr->gamma_table, png_ptr->gamma_from_1, | |
1387 png_ptr->gamma_to_1, png_ptr->gamma_16_table, | |
1388 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, | |
1389 png_ptr->gamma_shift | |
1390 #endif | |
1391 ); | |
1392 #endif | |
1393 | |
1394 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
1395 if ((png_ptr->transformations & PNG_GAMMA) && | |
1396 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
1397 !((png_ptr->transformations & PNG_BACKGROUND) && | |
1398 ((png_ptr->num_trans != 0) || | |
1399 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && | |
1400 #endif | |
1401 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) | |
1402 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1403 png_ptr->gamma_table, png_ptr->gamma_16_table, | |
1404 png_ptr->gamma_shift); | |
1405 #endif | |
1406 | |
1407 #if defined(PNG_READ_16_TO_8_SUPPORTED) | |
1408 if (png_ptr->transformations & PNG_16_TO_8) | |
1409 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1410 #endif | |
1411 | |
1412 #if defined(PNG_READ_DITHER_SUPPORTED) | |
1413 if (png_ptr->transformations & PNG_DITHER) | |
1414 { | |
1415 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1416 png_ptr->palette_lookup, png_ptr->dither_index); | |
1417 if(png_ptr->row_info.rowbytes == (png_uint_32)0) | |
1418 png_error(png_ptr, "png_do_dither returned rowbytes=0"); | |
1419 } | |
1420 #endif | |
1421 | |
1422 #if defined(PNG_READ_INVERT_SUPPORTED) | |
1423 if (png_ptr->transformations & PNG_INVERT_MONO) | |
1424 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1425 #endif | |
1426 | |
1427 #if defined(PNG_READ_SHIFT_SUPPORTED) | |
1428 if (png_ptr->transformations & PNG_SHIFT) | |
1429 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1430 &(png_ptr->shift)); | |
1431 #endif | |
1432 | |
1433 #if defined(PNG_READ_PACK_SUPPORTED) | |
1434 if (png_ptr->transformations & PNG_PACK) | |
1435 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1436 #endif | |
1437 | |
1438 #if defined(PNG_READ_BGR_SUPPORTED) | |
1439 if (png_ptr->transformations & PNG_BGR) | |
1440 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1441 #endif | |
1442 | |
1443 #if defined(PNG_READ_PACKSWAP_SUPPORTED) | |
1444 if (png_ptr->transformations & PNG_PACKSWAP) | |
1445 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1446 #endif | |
1447 | |
1448 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
1449 /* if gray -> RGB, do so now only if we did not do so above */ | |
1450 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && | |
1451 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) | |
1452 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1453 #endif | |
1454 | |
1455 #if defined(PNG_READ_FILLER_SUPPORTED) | |
1456 if (png_ptr->transformations & PNG_FILLER) | |
1457 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, | |
1458 (png_uint_32)png_ptr->filler, png_ptr->flags); | |
1459 #endif | |
1460 | |
1461 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) | |
1462 if (png_ptr->transformations & PNG_INVERT_ALPHA) | |
1463 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1464 #endif | |
1465 | |
1466 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) | |
1467 if (png_ptr->transformations & PNG_SWAP_ALPHA) | |
1468 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1469 #endif | |
1470 | |
1471 #if defined(PNG_READ_SWAP_SUPPORTED) | |
1472 if (png_ptr->transformations & PNG_SWAP_BYTES) | |
1473 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
1474 #endif | |
1475 | |
1476 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) | |
1477 if (png_ptr->transformations & PNG_USER_TRANSFORM) | |
1478 { | |
1479 if(png_ptr->read_user_transform_fn != NULL) | |
1480 (*(png_ptr->read_user_transform_fn)) /* user read transform function */ | |
1481 (png_ptr, /* png_ptr */ | |
1482 &(png_ptr->row_info), /* row_info: */ | |
1483 /* png_uint_32 width; width of row */ | |
1484 /* png_uint_32 rowbytes; number of bytes in row */ | |
1485 /* png_byte color_type; color type of pixels */ | |
1486 /* png_byte bit_depth; bit depth of samples */ | |
1487 /* png_byte channels; number of channels (1-4) */ | |
1488 /* png_byte pixel_depth; bits per pixel (depth*channels) */ | |
1489 png_ptr->row_buf + 1); /* start of pixel data for row */ | |
1490 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) | |
1491 if(png_ptr->user_transform_depth) | |
1492 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; | |
1493 if(png_ptr->user_transform_channels) | |
1494 png_ptr->row_info.channels = png_ptr->user_transform_channels; | |
1495 #endif | |
1496 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * | |
1497 png_ptr->row_info.channels); | |
1498 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, | |
1499 png_ptr->row_info.width); | |
1500 } | |
1501 #endif | |
1502 | |
1503 } | |
1504 | |
1505 #if defined(PNG_READ_PACK_SUPPORTED) | |
1506 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, | |
1507 * without changing the actual values. Thus, if you had a row with | |
1508 * a bit depth of 1, you would end up with bytes that only contained | |
1509 * the numbers 0 or 1. If you would rather they contain 0 and 255, use | |
1510 * png_do_shift() after this. | |
1511 */ | |
1512 void /* PRIVATE */ | |
1513 png_do_unpack(png_row_infop row_info, png_bytep row) | |
1514 { | |
1515 png_debug(1, "in png_do_unpack\n"); | |
1516 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1517 if (row != NULL && row_info != NULL && row_info->bit_depth < 8) | |
1518 #else | |
1519 if (row_info->bit_depth < 8) | |
1520 #endif | |
1521 { | |
1522 png_uint_32 i; | |
1523 png_uint_32 row_width=row_info->width; | |
1524 | |
1525 switch (row_info->bit_depth) | |
1526 { | |
1527 case 1: | |
1528 { | |
1529 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); | |
1530 png_bytep dp = row + (png_size_t)row_width - 1; | |
1531 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); | |
1532 for (i = 0; i < row_width; i++) | |
1533 { | |
1534 *dp = (png_byte)((*sp >> shift) & 0x01); | |
1535 if (shift == 7) | |
1536 { | |
1537 shift = 0; | |
1538 sp--; | |
1539 } | |
1540 else | |
1541 shift++; | |
1542 | |
1543 dp--; | |
1544 } | |
1545 break; | |
1546 } | |
1547 case 2: | |
1548 { | |
1549 | |
1550 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); | |
1551 png_bytep dp = row + (png_size_t)row_width - 1; | |
1552 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); | |
1553 for (i = 0; i < row_width; i++) | |
1554 { | |
1555 *dp = (png_byte)((*sp >> shift) & 0x03); | |
1556 if (shift == 6) | |
1557 { | |
1558 shift = 0; | |
1559 sp--; | |
1560 } | |
1561 else | |
1562 shift += 2; | |
1563 | |
1564 dp--; | |
1565 } | |
1566 break; | |
1567 } | |
1568 case 4: | |
1569 { | |
1570 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); | |
1571 png_bytep dp = row + (png_size_t)row_width - 1; | |
1572 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); | |
1573 for (i = 0; i < row_width; i++) | |
1574 { | |
1575 *dp = (png_byte)((*sp >> shift) & 0x0f); | |
1576 if (shift == 4) | |
1577 { | |
1578 shift = 0; | |
1579 sp--; | |
1580 } | |
1581 else | |
1582 shift = 4; | |
1583 | |
1584 dp--; | |
1585 } | |
1586 break; | |
1587 } | |
1588 } | |
1589 row_info->bit_depth = 8; | |
1590 row_info->pixel_depth = (png_byte)(8 * row_info->channels); | |
1591 row_info->rowbytes = row_width * row_info->channels; | |
1592 } | |
1593 } | |
1594 #endif | |
1595 | |
1596 #if defined(PNG_READ_SHIFT_SUPPORTED) | |
1597 /* Reverse the effects of png_do_shift. This routine merely shifts the | |
1598 * pixels back to their significant bits values. Thus, if you have | |
1599 * a row of bit depth 8, but only 5 are significant, this will shift | |
1600 * the values back to 0 through 31. | |
1601 */ | |
1602 void /* PRIVATE */ | |
1603 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) | |
1604 { | |
1605 png_debug(1, "in png_do_unshift\n"); | |
1606 if ( | |
1607 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1608 row != NULL && row_info != NULL && sig_bits != NULL && | |
1609 #endif | |
1610 row_info->color_type != PNG_COLOR_TYPE_PALETTE) | |
1611 { | |
1612 int shift[4]; | |
1613 int channels = 0; | |
1614 int c; | |
1615 png_uint_16 value = 0; | |
1616 png_uint_32 row_width = row_info->width; | |
1617 | |
1618 if (row_info->color_type & PNG_COLOR_MASK_COLOR) | |
1619 { | |
1620 shift[channels++] = row_info->bit_depth - sig_bits->red; | |
1621 shift[channels++] = row_info->bit_depth - sig_bits->green; | |
1622 shift[channels++] = row_info->bit_depth - sig_bits->blue; | |
1623 } | |
1624 else | |
1625 { | |
1626 shift[channels++] = row_info->bit_depth - sig_bits->gray; | |
1627 } | |
1628 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) | |
1629 { | |
1630 shift[channels++] = row_info->bit_depth - sig_bits->alpha; | |
1631 } | |
1632 | |
1633 for (c = 0; c < channels; c++) | |
1634 { | |
1635 if (shift[c] <= 0) | |
1636 shift[c] = 0; | |
1637 else | |
1638 value = 1; | |
1639 } | |
1640 | |
1641 if (!value) | |
1642 return; | |
1643 | |
1644 switch (row_info->bit_depth) | |
1645 { | |
1646 case 2: | |
1647 { | |
1648 png_bytep bp; | |
1649 png_uint_32 i; | |
1650 png_uint_32 istop = row_info->rowbytes; | |
1651 | |
1652 for (bp = row, i = 0; i < istop; i++) | |
1653 { | |
1654 *bp >>= 1; | |
1655 *bp++ &= 0x55; | |
1656 } | |
1657 break; | |
1658 } | |
1659 case 4: | |
1660 { | |
1661 png_bytep bp = row; | |
1662 png_uint_32 i; | |
1663 png_uint_32 istop = row_info->rowbytes; | |
1664 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | | |
1665 (png_byte)((int)0xf >> shift[0])); | |
1666 | |
1667 for (i = 0; i < istop; i++) | |
1668 { | |
1669 *bp >>= shift[0]; | |
1670 *bp++ &= mask; | |
1671 } | |
1672 break; | |
1673 } | |
1674 case 8: | |
1675 { | |
1676 png_bytep bp = row; | |
1677 png_uint_32 i; | |
1678 png_uint_32 istop = row_width * channels; | |
1679 | |
1680 for (i = 0; i < istop; i++) | |
1681 { | |
1682 *bp++ >>= shift[i%channels]; | |
1683 } | |
1684 break; | |
1685 } | |
1686 case 16: | |
1687 { | |
1688 png_bytep bp = row; | |
1689 png_uint_32 i; | |
1690 png_uint_32 istop = channels * row_width; | |
1691 | |
1692 for (i = 0; i < istop; i++) | |
1693 { | |
1694 value = (png_uint_16)((*bp << 8) + *(bp + 1)); | |
1695 value >>= shift[i%channels]; | |
1696 *bp++ = (png_byte)(value >> 8); | |
1697 *bp++ = (png_byte)(value & 0xff); | |
1698 } | |
1699 break; | |
1700 } | |
1701 } | |
1702 } | |
1703 } | |
1704 #endif | |
1705 | |
1706 #if defined(PNG_READ_16_TO_8_SUPPORTED) | |
1707 /* chop rows of bit depth 16 down to 8 */ | |
1708 void /* PRIVATE */ | |
1709 png_do_chop(png_row_infop row_info, png_bytep row) | |
1710 { | |
1711 png_debug(1, "in png_do_chop\n"); | |
1712 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1713 if (row != NULL && row_info != NULL && row_info->bit_depth == 16) | |
1714 #else | |
1715 if (row_info->bit_depth == 16) | |
1716 #endif | |
1717 { | |
1718 png_bytep sp = row; | |
1719 png_bytep dp = row; | |
1720 png_uint_32 i; | |
1721 png_uint_32 istop = row_info->width * row_info->channels; | |
1722 | |
1723 for (i = 0; i<istop; i++, sp += 2, dp++) | |
1724 { | |
1725 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED) | |
1726 /* This does a more accurate scaling of the 16-bit color | |
1727 * value, rather than a simple low-byte truncation. | |
1728 * | |
1729 * What the ideal calculation should be: | |
1730 * *dp = (((((png_uint_32)(*sp) << 8) | | |
1731 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L; | |
1732 * | |
1733 * GRR: no, I think this is what it really should be: | |
1734 * *dp = (((((png_uint_32)(*sp) << 8) | | |
1735 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L; | |
1736 * | |
1737 * GRR: here's the exact calculation with shifts: | |
1738 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L; | |
1739 * *dp = (temp - (temp >> 8)) >> 8; | |
1740 * | |
1741 * Approximate calculation with shift/add instead of multiply/divide: | |
1742 * *dp = ((((png_uint_32)(*sp) << 8) | | |
1743 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; | |
1744 * | |
1745 * What we actually do to avoid extra shifting and conversion: | |
1746 */ | |
1747 | |
1748 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); | |
1749 #else | |
1750 /* Simply discard the low order byte */ | |
1751 *dp = *sp; | |
1752 #endif | |
1753 } | |
1754 row_info->bit_depth = 8; | |
1755 row_info->pixel_depth = (png_byte)(8 * row_info->channels); | |
1756 row_info->rowbytes = row_info->width * row_info->channels; | |
1757 } | |
1758 } | |
1759 #endif | |
1760 | |
1761 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) | |
1762 void /* PRIVATE */ | |
1763 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) | |
1764 { | |
1765 png_debug(1, "in png_do_read_swap_alpha\n"); | |
1766 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1767 if (row != NULL && row_info != NULL) | |
1768 #endif | |
1769 { | |
1770 png_uint_32 row_width = row_info->width; | |
1771 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
1772 { | |
1773 /* This converts from RGBA to ARGB */ | |
1774 if (row_info->bit_depth == 8) | |
1775 { | |
1776 png_bytep sp = row + row_info->rowbytes; | |
1777 png_bytep dp = sp; | |
1778 png_byte save; | |
1779 png_uint_32 i; | |
1780 | |
1781 for (i = 0; i < row_width; i++) | |
1782 { | |
1783 save = *(--sp); | |
1784 *(--dp) = *(--sp); | |
1785 *(--dp) = *(--sp); | |
1786 *(--dp) = *(--sp); | |
1787 *(--dp) = save; | |
1788 } | |
1789 } | |
1790 /* This converts from RRGGBBAA to AARRGGBB */ | |
1791 else | |
1792 { | |
1793 png_bytep sp = row + row_info->rowbytes; | |
1794 png_bytep dp = sp; | |
1795 png_byte save[2]; | |
1796 png_uint_32 i; | |
1797 | |
1798 for (i = 0; i < row_width; i++) | |
1799 { | |
1800 save[0] = *(--sp); | |
1801 save[1] = *(--sp); | |
1802 *(--dp) = *(--sp); | |
1803 *(--dp) = *(--sp); | |
1804 *(--dp) = *(--sp); | |
1805 *(--dp) = *(--sp); | |
1806 *(--dp) = *(--sp); | |
1807 *(--dp) = *(--sp); | |
1808 *(--dp) = save[0]; | |
1809 *(--dp) = save[1]; | |
1810 } | |
1811 } | |
1812 } | |
1813 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
1814 { | |
1815 /* This converts from GA to AG */ | |
1816 if (row_info->bit_depth == 8) | |
1817 { | |
1818 png_bytep sp = row + row_info->rowbytes; | |
1819 png_bytep dp = sp; | |
1820 png_byte save; | |
1821 png_uint_32 i; | |
1822 | |
1823 for (i = 0; i < row_width; i++) | |
1824 { | |
1825 save = *(--sp); | |
1826 *(--dp) = *(--sp); | |
1827 *(--dp) = save; | |
1828 } | |
1829 } | |
1830 /* This converts from GGAA to AAGG */ | |
1831 else | |
1832 { | |
1833 png_bytep sp = row + row_info->rowbytes; | |
1834 png_bytep dp = sp; | |
1835 png_byte save[2]; | |
1836 png_uint_32 i; | |
1837 | |
1838 for (i = 0; i < row_width; i++) | |
1839 { | |
1840 save[0] = *(--sp); | |
1841 save[1] = *(--sp); | |
1842 *(--dp) = *(--sp); | |
1843 *(--dp) = *(--sp); | |
1844 *(--dp) = save[0]; | |
1845 *(--dp) = save[1]; | |
1846 } | |
1847 } | |
1848 } | |
1849 } | |
1850 } | |
1851 #endif | |
1852 | |
1853 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) | |
1854 void /* PRIVATE */ | |
1855 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) | |
1856 { | |
1857 png_debug(1, "in png_do_read_invert_alpha\n"); | |
1858 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1859 if (row != NULL && row_info != NULL) | |
1860 #endif | |
1861 { | |
1862 png_uint_32 row_width = row_info->width; | |
1863 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
1864 { | |
1865 /* This inverts the alpha channel in RGBA */ | |
1866 if (row_info->bit_depth == 8) | |
1867 { | |
1868 png_bytep sp = row + row_info->rowbytes; | |
1869 png_bytep dp = sp; | |
1870 png_uint_32 i; | |
1871 | |
1872 for (i = 0; i < row_width; i++) | |
1873 { | |
1874 *(--dp) = (png_byte)(255 - *(--sp)); | |
1875 | |
1876 /* This does nothing: | |
1877 *(--dp) = *(--sp); | |
1878 *(--dp) = *(--sp); | |
1879 *(--dp) = *(--sp); | |
1880 We can replace it with: | |
1881 */ | |
1882 sp-=3; | |
1883 dp=sp; | |
1884 } | |
1885 } | |
1886 /* This inverts the alpha channel in RRGGBBAA */ | |
1887 else | |
1888 { | |
1889 png_bytep sp = row + row_info->rowbytes; | |
1890 png_bytep dp = sp; | |
1891 png_uint_32 i; | |
1892 | |
1893 for (i = 0; i < row_width; i++) | |
1894 { | |
1895 *(--dp) = (png_byte)(255 - *(--sp)); | |
1896 *(--dp) = (png_byte)(255 - *(--sp)); | |
1897 | |
1898 /* This does nothing: | |
1899 *(--dp) = *(--sp); | |
1900 *(--dp) = *(--sp); | |
1901 *(--dp) = *(--sp); | |
1902 *(--dp) = *(--sp); | |
1903 *(--dp) = *(--sp); | |
1904 *(--dp) = *(--sp); | |
1905 We can replace it with: | |
1906 */ | |
1907 sp-=6; | |
1908 dp=sp; | |
1909 } | |
1910 } | |
1911 } | |
1912 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
1913 { | |
1914 /* This inverts the alpha channel in GA */ | |
1915 if (row_info->bit_depth == 8) | |
1916 { | |
1917 png_bytep sp = row + row_info->rowbytes; | |
1918 png_bytep dp = sp; | |
1919 png_uint_32 i; | |
1920 | |
1921 for (i = 0; i < row_width; i++) | |
1922 { | |
1923 *(--dp) = (png_byte)(255 - *(--sp)); | |
1924 *(--dp) = *(--sp); | |
1925 } | |
1926 } | |
1927 /* This inverts the alpha channel in GGAA */ | |
1928 else | |
1929 { | |
1930 png_bytep sp = row + row_info->rowbytes; | |
1931 png_bytep dp = sp; | |
1932 png_uint_32 i; | |
1933 | |
1934 for (i = 0; i < row_width; i++) | |
1935 { | |
1936 *(--dp) = (png_byte)(255 - *(--sp)); | |
1937 *(--dp) = (png_byte)(255 - *(--sp)); | |
1938 /* | |
1939 *(--dp) = *(--sp); | |
1940 *(--dp) = *(--sp); | |
1941 */ | |
1942 sp-=2; | |
1943 dp=sp; | |
1944 } | |
1945 } | |
1946 } | |
1947 } | |
1948 } | |
1949 #endif | |
1950 | |
1951 #if defined(PNG_READ_FILLER_SUPPORTED) | |
1952 /* Add filler channel if we have RGB color */ | |
1953 void /* PRIVATE */ | |
1954 png_do_read_filler(png_row_infop row_info, png_bytep row, | |
1955 png_uint_32 filler, png_uint_32 flags) | |
1956 { | |
1957 png_uint_32 i; | |
1958 png_uint_32 row_width = row_info->width; | |
1959 | |
1960 png_byte hi_filler = (png_byte)((filler>>8) & 0xff); | |
1961 png_byte lo_filler = (png_byte)(filler & 0xff); | |
1962 | |
1963 png_debug(1, "in png_do_read_filler\n"); | |
1964 if ( | |
1965 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
1966 row != NULL && row_info != NULL && | |
1967 #endif | |
1968 row_info->color_type == PNG_COLOR_TYPE_GRAY) | |
1969 { | |
1970 if(row_info->bit_depth == 8) | |
1971 { | |
1972 /* This changes the data from G to GX */ | |
1973 if (flags & PNG_FLAG_FILLER_AFTER) | |
1974 { | |
1975 png_bytep sp = row + (png_size_t)row_width; | |
1976 png_bytep dp = sp + (png_size_t)row_width; | |
1977 for (i = 1; i < row_width; i++) | |
1978 { | |
1979 *(--dp) = lo_filler; | |
1980 *(--dp) = *(--sp); | |
1981 } | |
1982 *(--dp) = lo_filler; | |
1983 row_info->channels = 2; | |
1984 row_info->pixel_depth = 16; | |
1985 row_info->rowbytes = row_width * 2; | |
1986 } | |
1987 /* This changes the data from G to XG */ | |
1988 else | |
1989 { | |
1990 png_bytep sp = row + (png_size_t)row_width; | |
1991 png_bytep dp = sp + (png_size_t)row_width; | |
1992 for (i = 0; i < row_width; i++) | |
1993 { | |
1994 *(--dp) = *(--sp); | |
1995 *(--dp) = lo_filler; | |
1996 } | |
1997 row_info->channels = 2; | |
1998 row_info->pixel_depth = 16; | |
1999 row_info->rowbytes = row_width * 2; | |
2000 } | |
2001 } | |
2002 else if(row_info->bit_depth == 16) | |
2003 { | |
2004 /* This changes the data from GG to GGXX */ | |
2005 if (flags & PNG_FLAG_FILLER_AFTER) | |
2006 { | |
2007 png_bytep sp = row + (png_size_t)row_width * 2; | |
2008 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2009 for (i = 1; i < row_width; i++) | |
2010 { | |
2011 *(--dp) = hi_filler; | |
2012 *(--dp) = lo_filler; | |
2013 *(--dp) = *(--sp); | |
2014 *(--dp) = *(--sp); | |
2015 } | |
2016 *(--dp) = hi_filler; | |
2017 *(--dp) = lo_filler; | |
2018 row_info->channels = 2; | |
2019 row_info->pixel_depth = 32; | |
2020 row_info->rowbytes = row_width * 4; | |
2021 } | |
2022 /* This changes the data from GG to XXGG */ | |
2023 else | |
2024 { | |
2025 png_bytep sp = row + (png_size_t)row_width * 2; | |
2026 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2027 for (i = 0; i < row_width; i++) | |
2028 { | |
2029 *(--dp) = *(--sp); | |
2030 *(--dp) = *(--sp); | |
2031 *(--dp) = hi_filler; | |
2032 *(--dp) = lo_filler; | |
2033 } | |
2034 row_info->channels = 2; | |
2035 row_info->pixel_depth = 32; | |
2036 row_info->rowbytes = row_width * 4; | |
2037 } | |
2038 } | |
2039 } /* COLOR_TYPE == GRAY */ | |
2040 else if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
2041 { | |
2042 if(row_info->bit_depth == 8) | |
2043 { | |
2044 /* This changes the data from RGB to RGBX */ | |
2045 if (flags & PNG_FLAG_FILLER_AFTER) | |
2046 { | |
2047 png_bytep sp = row + (png_size_t)row_width * 3; | |
2048 png_bytep dp = sp + (png_size_t)row_width; | |
2049 for (i = 1; i < row_width; i++) | |
2050 { | |
2051 *(--dp) = lo_filler; | |
2052 *(--dp) = *(--sp); | |
2053 *(--dp) = *(--sp); | |
2054 *(--dp) = *(--sp); | |
2055 } | |
2056 *(--dp) = lo_filler; | |
2057 row_info->channels = 4; | |
2058 row_info->pixel_depth = 32; | |
2059 row_info->rowbytes = row_width * 4; | |
2060 } | |
2061 /* This changes the data from RGB to XRGB */ | |
2062 else | |
2063 { | |
2064 png_bytep sp = row + (png_size_t)row_width * 3; | |
2065 png_bytep dp = sp + (png_size_t)row_width; | |
2066 for (i = 0; i < row_width; i++) | |
2067 { | |
2068 *(--dp) = *(--sp); | |
2069 *(--dp) = *(--sp); | |
2070 *(--dp) = *(--sp); | |
2071 *(--dp) = lo_filler; | |
2072 } | |
2073 row_info->channels = 4; | |
2074 row_info->pixel_depth = 32; | |
2075 row_info->rowbytes = row_width * 4; | |
2076 } | |
2077 } | |
2078 else if(row_info->bit_depth == 16) | |
2079 { | |
2080 /* This changes the data from RRGGBB to RRGGBBXX */ | |
2081 if (flags & PNG_FLAG_FILLER_AFTER) | |
2082 { | |
2083 png_bytep sp = row + (png_size_t)row_width * 6; | |
2084 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2085 for (i = 1; i < row_width; i++) | |
2086 { | |
2087 *(--dp) = hi_filler; | |
2088 *(--dp) = lo_filler; | |
2089 *(--dp) = *(--sp); | |
2090 *(--dp) = *(--sp); | |
2091 *(--dp) = *(--sp); | |
2092 *(--dp) = *(--sp); | |
2093 *(--dp) = *(--sp); | |
2094 *(--dp) = *(--sp); | |
2095 } | |
2096 *(--dp) = hi_filler; | |
2097 *(--dp) = lo_filler; | |
2098 row_info->channels = 4; | |
2099 row_info->pixel_depth = 64; | |
2100 row_info->rowbytes = row_width * 8; | |
2101 } | |
2102 /* This changes the data from RRGGBB to XXRRGGBB */ | |
2103 else | |
2104 { | |
2105 png_bytep sp = row + (png_size_t)row_width * 6; | |
2106 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2107 for (i = 0; i < row_width; i++) | |
2108 { | |
2109 *(--dp) = *(--sp); | |
2110 *(--dp) = *(--sp); | |
2111 *(--dp) = *(--sp); | |
2112 *(--dp) = *(--sp); | |
2113 *(--dp) = *(--sp); | |
2114 *(--dp) = *(--sp); | |
2115 *(--dp) = hi_filler; | |
2116 *(--dp) = lo_filler; | |
2117 } | |
2118 row_info->channels = 4; | |
2119 row_info->pixel_depth = 64; | |
2120 row_info->rowbytes = row_width * 8; | |
2121 } | |
2122 } | |
2123 } /* COLOR_TYPE == RGB */ | |
2124 } | |
2125 #endif | |
2126 | |
2127 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) | |
2128 /* expand grayscale files to RGB, with or without alpha */ | |
2129 void /* PRIVATE */ | |
2130 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) | |
2131 { | |
2132 png_uint_32 i; | |
2133 png_uint_32 row_width = row_info->width; | |
2134 | |
2135 png_debug(1, "in png_do_gray_to_rgb\n"); | |
2136 if (row_info->bit_depth >= 8 && | |
2137 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
2138 row != NULL && row_info != NULL && | |
2139 #endif | |
2140 !(row_info->color_type & PNG_COLOR_MASK_COLOR)) | |
2141 { | |
2142 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) | |
2143 { | |
2144 if (row_info->bit_depth == 8) | |
2145 { | |
2146 png_bytep sp = row + (png_size_t)row_width - 1; | |
2147 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2148 for (i = 0; i < row_width; i++) | |
2149 { | |
2150 *(dp--) = *sp; | |
2151 *(dp--) = *sp; | |
2152 *(dp--) = *(sp--); | |
2153 } | |
2154 } | |
2155 else | |
2156 { | |
2157 png_bytep sp = row + (png_size_t)row_width * 2 - 1; | |
2158 png_bytep dp = sp + (png_size_t)row_width * 4; | |
2159 for (i = 0; i < row_width; i++) | |
2160 { | |
2161 *(dp--) = *sp; | |
2162 *(dp--) = *(sp - 1); | |
2163 *(dp--) = *sp; | |
2164 *(dp--) = *(sp - 1); | |
2165 *(dp--) = *(sp--); | |
2166 *(dp--) = *(sp--); | |
2167 } | |
2168 } | |
2169 } | |
2170 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
2171 { | |
2172 if (row_info->bit_depth == 8) | |
2173 { | |
2174 png_bytep sp = row + (png_size_t)row_width * 2 - 1; | |
2175 png_bytep dp = sp + (png_size_t)row_width * 2; | |
2176 for (i = 0; i < row_width; i++) | |
2177 { | |
2178 *(dp--) = *(sp--); | |
2179 *(dp--) = *sp; | |
2180 *(dp--) = *sp; | |
2181 *(dp--) = *(sp--); | |
2182 } | |
2183 } | |
2184 else | |
2185 { | |
2186 png_bytep sp = row + (png_size_t)row_width * 4 - 1; | |
2187 png_bytep dp = sp + (png_size_t)row_width * 4; | |
2188 for (i = 0; i < row_width; i++) | |
2189 { | |
2190 *(dp--) = *(sp--); | |
2191 *(dp--) = *(sp--); | |
2192 *(dp--) = *sp; | |
2193 *(dp--) = *(sp - 1); | |
2194 *(dp--) = *sp; | |
2195 *(dp--) = *(sp - 1); | |
2196 *(dp--) = *(sp--); | |
2197 *(dp--) = *(sp--); | |
2198 } | |
2199 } | |
2200 } | |
2201 row_info->channels += (png_byte)2; | |
2202 row_info->color_type |= PNG_COLOR_MASK_COLOR; | |
2203 row_info->pixel_depth = (png_byte)(row_info->channels * | |
2204 row_info->bit_depth); | |
2205 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
2206 } | |
2207 } | |
2208 #endif | |
2209 | |
2210 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
2211 /* reduce RGB files to grayscale, with or without alpha | |
2212 * using the equation given in Poynton's ColorFAQ at | |
2213 * <http://www.inforamp.net/~poynton/> | |
2214 * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net | |
2215 * | |
2216 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B | |
2217 * | |
2218 * We approximate this with | |
2219 * | |
2220 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B | |
2221 * | |
2222 * which can be expressed with integers as | |
2223 * | |
2224 * Y = (6969 * R + 23434 * G + 2365 * B)/32768 | |
2225 * | |
2226 * The calculation is to be done in a linear colorspace. | |
2227 * | |
2228 * Other integer coefficents can be used via png_set_rgb_to_gray(). | |
2229 */ | |
2230 int /* PRIVATE */ | |
2231 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) | |
2232 | |
2233 { | |
2234 png_uint_32 i; | |
2235 | |
2236 png_uint_32 row_width = row_info->width; | |
2237 int rgb_error = 0; | |
2238 | |
2239 png_debug(1, "in png_do_rgb_to_gray\n"); | |
2240 if ( | |
2241 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
2242 row != NULL && row_info != NULL && | |
2243 #endif | |
2244 (row_info->color_type & PNG_COLOR_MASK_COLOR)) | |
2245 { | |
2246 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; | |
2247 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; | |
2248 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; | |
2249 | |
2250 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
2251 { | |
2252 if (row_info->bit_depth == 8) | |
2253 { | |
2254 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2255 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) | |
2256 { | |
2257 png_bytep sp = row; | |
2258 png_bytep dp = row; | |
2259 | |
2260 for (i = 0; i < row_width; i++) | |
2261 { | |
2262 png_byte red = png_ptr->gamma_to_1[*(sp++)]; | |
2263 png_byte green = png_ptr->gamma_to_1[*(sp++)]; | |
2264 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; | |
2265 if(red != green || red != blue) | |
2266 { | |
2267 rgb_error |= 1; | |
2268 *(dp++) = png_ptr->gamma_from_1[ | |
2269 (rc*red+gc*green+bc*blue)>>15]; | |
2270 } | |
2271 else | |
2272 *(dp++) = *(sp-1); | |
2273 } | |
2274 } | |
2275 else | |
2276 #endif | |
2277 { | |
2278 png_bytep sp = row; | |
2279 png_bytep dp = row; | |
2280 for (i = 0; i < row_width; i++) | |
2281 { | |
2282 png_byte red = *(sp++); | |
2283 png_byte green = *(sp++); | |
2284 png_byte blue = *(sp++); | |
2285 if(red != green || red != blue) | |
2286 { | |
2287 rgb_error |= 1; | |
2288 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); | |
2289 } | |
2290 else | |
2291 *(dp++) = *(sp-1); | |
2292 } | |
2293 } | |
2294 } | |
2295 | |
2296 else /* RGB bit_depth == 16 */ | |
2297 { | |
2298 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2299 if (png_ptr->gamma_16_to_1 != NULL && | |
2300 png_ptr->gamma_16_from_1 != NULL) | |
2301 { | |
2302 png_bytep sp = row; | |
2303 png_bytep dp = row; | |
2304 for (i = 0; i < row_width; i++) | |
2305 { | |
2306 png_uint_16 red, green, blue, w; | |
2307 | |
2308 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2309 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2310 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2311 | |
2312 if(red == green && red == blue) | |
2313 w = red; | |
2314 else | |
2315 { | |
2316 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> | |
2317 png_ptr->gamma_shift][red>>8]; | |
2318 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> | |
2319 png_ptr->gamma_shift][green>>8]; | |
2320 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> | |
2321 png_ptr->gamma_shift][blue>>8]; | |
2322 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 | |
2323 + bc*blue_1)>>15); | |
2324 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> | |
2325 png_ptr->gamma_shift][gray16 >> 8]; | |
2326 rgb_error |= 1; | |
2327 } | |
2328 | |
2329 *(dp++) = (png_byte)((w>>8) & 0xff); | |
2330 *(dp++) = (png_byte)(w & 0xff); | |
2331 } | |
2332 } | |
2333 else | |
2334 #endif | |
2335 { | |
2336 png_bytep sp = row; | |
2337 png_bytep dp = row; | |
2338 for (i = 0; i < row_width; i++) | |
2339 { | |
2340 png_uint_16 red, green, blue, gray16; | |
2341 | |
2342 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2343 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2344 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2345 | |
2346 if(red != green || red != blue) | |
2347 rgb_error |= 1; | |
2348 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); | |
2349 *(dp++) = (png_byte)((gray16>>8) & 0xff); | |
2350 *(dp++) = (png_byte)(gray16 & 0xff); | |
2351 } | |
2352 } | |
2353 } | |
2354 } | |
2355 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
2356 { | |
2357 if (row_info->bit_depth == 8) | |
2358 { | |
2359 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2360 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) | |
2361 { | |
2362 png_bytep sp = row; | |
2363 png_bytep dp = row; | |
2364 for (i = 0; i < row_width; i++) | |
2365 { | |
2366 png_byte red = png_ptr->gamma_to_1[*(sp++)]; | |
2367 png_byte green = png_ptr->gamma_to_1[*(sp++)]; | |
2368 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; | |
2369 if(red != green || red != blue) | |
2370 rgb_error |= 1; | |
2371 *(dp++) = png_ptr->gamma_from_1 | |
2372 [(rc*red + gc*green + bc*blue)>>15]; | |
2373 *(dp++) = *(sp++); /* alpha */ | |
2374 } | |
2375 } | |
2376 else | |
2377 #endif | |
2378 { | |
2379 png_bytep sp = row; | |
2380 png_bytep dp = row; | |
2381 for (i = 0; i < row_width; i++) | |
2382 { | |
2383 png_byte red = *(sp++); | |
2384 png_byte green = *(sp++); | |
2385 png_byte blue = *(sp++); | |
2386 if(red != green || red != blue) | |
2387 rgb_error |= 1; | |
2388 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); | |
2389 *(dp++) = *(sp++); /* alpha */ | |
2390 } | |
2391 } | |
2392 } | |
2393 else /* RGBA bit_depth == 16 */ | |
2394 { | |
2395 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2396 if (png_ptr->gamma_16_to_1 != NULL && | |
2397 png_ptr->gamma_16_from_1 != NULL) | |
2398 { | |
2399 png_bytep sp = row; | |
2400 png_bytep dp = row; | |
2401 for (i = 0; i < row_width; i++) | |
2402 { | |
2403 png_uint_16 red, green, blue, w; | |
2404 | |
2405 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2406 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2407 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; | |
2408 | |
2409 if(red == green && red == blue) | |
2410 w = red; | |
2411 else | |
2412 { | |
2413 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> | |
2414 png_ptr->gamma_shift][red>>8]; | |
2415 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> | |
2416 png_ptr->gamma_shift][green>>8]; | |
2417 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> | |
2418 png_ptr->gamma_shift][blue>>8]; | |
2419 png_uint_16 gray16 = (png_uint_16)((rc * red_1 | |
2420 + gc * green_1 + bc * blue_1)>>15); | |
2421 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> | |
2422 png_ptr->gamma_shift][gray16 >> 8]; | |
2423 rgb_error |= 1; | |
2424 } | |
2425 | |
2426 *(dp++) = (png_byte)((w>>8) & 0xff); | |
2427 *(dp++) = (png_byte)(w & 0xff); | |
2428 *(dp++) = *(sp++); /* alpha */ | |
2429 *(dp++) = *(sp++); | |
2430 } | |
2431 } | |
2432 else | |
2433 #endif | |
2434 { | |
2435 png_bytep sp = row; | |
2436 png_bytep dp = row; | |
2437 for (i = 0; i < row_width; i++) | |
2438 { | |
2439 png_uint_16 red, green, blue, gray16; | |
2440 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; | |
2441 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; | |
2442 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; | |
2443 if(red != green || red != blue) | |
2444 rgb_error |= 1; | |
2445 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); | |
2446 *(dp++) = (png_byte)((gray16>>8) & 0xff); | |
2447 *(dp++) = (png_byte)(gray16 & 0xff); | |
2448 *(dp++) = *(sp++); /* alpha */ | |
2449 *(dp++) = *(sp++); | |
2450 } | |
2451 } | |
2452 } | |
2453 } | |
2454 row_info->channels -= (png_byte)2; | |
2455 row_info->color_type &= ~PNG_COLOR_MASK_COLOR; | |
2456 row_info->pixel_depth = (png_byte)(row_info->channels * | |
2457 row_info->bit_depth); | |
2458 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
2459 } | |
2460 return rgb_error; | |
2461 } | |
2462 #endif | |
2463 | |
2464 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth | |
2465 * large of png_color. This lets grayscale images be treated as | |
2466 * paletted. Most useful for gamma correction and simplification | |
2467 * of code. | |
2468 */ | |
2469 void PNGAPI | |
2470 png_build_grayscale_palette(int bit_depth, png_colorp palette) | |
2471 { | |
2472 int num_palette; | |
2473 int color_inc; | |
2474 int i; | |
2475 int v; | |
2476 | |
2477 png_debug(1, "in png_do_build_grayscale_palette\n"); | |
2478 if (palette == NULL) | |
2479 return; | |
2480 | |
2481 switch (bit_depth) | |
2482 { | |
2483 case 1: | |
2484 num_palette = 2; | |
2485 color_inc = 0xff; | |
2486 break; | |
2487 case 2: | |
2488 num_palette = 4; | |
2489 color_inc = 0x55; | |
2490 break; | |
2491 case 4: | |
2492 num_palette = 16; | |
2493 color_inc = 0x11; | |
2494 break; | |
2495 case 8: | |
2496 num_palette = 256; | |
2497 color_inc = 1; | |
2498 break; | |
2499 default: | |
2500 num_palette = 0; | |
2501 color_inc = 0; | |
2502 break; | |
2503 } | |
2504 | |
2505 for (i = 0, v = 0; i < num_palette; i++, v += color_inc) | |
2506 { | |
2507 palette[i].red = (png_byte)v; | |
2508 palette[i].green = (png_byte)v; | |
2509 palette[i].blue = (png_byte)v; | |
2510 } | |
2511 } | |
2512 | |
2513 /* This function is currently unused. Do we really need it? */ | |
2514 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) | |
2515 void /* PRIVATE */ | |
2516 png_correct_palette(png_structp png_ptr, png_colorp palette, | |
2517 int num_palette) | |
2518 { | |
2519 png_debug(1, "in png_correct_palette\n"); | |
2520 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ | |
2521 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) | |
2522 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) | |
2523 { | |
2524 png_color back, back_1; | |
2525 | |
2526 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) | |
2527 { | |
2528 back.red = png_ptr->gamma_table[png_ptr->background.red]; | |
2529 back.green = png_ptr->gamma_table[png_ptr->background.green]; | |
2530 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; | |
2531 | |
2532 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; | |
2533 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; | |
2534 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; | |
2535 } | |
2536 else | |
2537 { | |
2538 double g; | |
2539 | |
2540 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); | |
2541 | |
2542 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || | |
2543 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) | |
2544 { | |
2545 back.red = png_ptr->background.red; | |
2546 back.green = png_ptr->background.green; | |
2547 back.blue = png_ptr->background.blue; | |
2548 } | |
2549 else | |
2550 { | |
2551 back.red = | |
2552 (png_byte)(pow((double)png_ptr->background.red/255, g) * | |
2553 255.0 + 0.5); | |
2554 back.green = | |
2555 (png_byte)(pow((double)png_ptr->background.green/255, g) * | |
2556 255.0 + 0.5); | |
2557 back.blue = | |
2558 (png_byte)(pow((double)png_ptr->background.blue/255, g) * | |
2559 255.0 + 0.5); | |
2560 } | |
2561 | |
2562 g = 1.0 / png_ptr->background_gamma; | |
2563 | |
2564 back_1.red = | |
2565 (png_byte)(pow((double)png_ptr->background.red/255, g) * | |
2566 255.0 + 0.5); | |
2567 back_1.green = | |
2568 (png_byte)(pow((double)png_ptr->background.green/255, g) * | |
2569 255.0 + 0.5); | |
2570 back_1.blue = | |
2571 (png_byte)(pow((double)png_ptr->background.blue/255, g) * | |
2572 255.0 + 0.5); | |
2573 } | |
2574 | |
2575 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
2576 { | |
2577 png_uint_32 i; | |
2578 | |
2579 for (i = 0; i < (png_uint_32)num_palette; i++) | |
2580 { | |
2581 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) | |
2582 { | |
2583 palette[i] = back; | |
2584 } | |
2585 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) | |
2586 { | |
2587 png_byte v, w; | |
2588 | |
2589 v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; | |
2590 png_composite(w, v, png_ptr->trans[i], back_1.red); | |
2591 palette[i].red = png_ptr->gamma_from_1[w]; | |
2592 | |
2593 v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; | |
2594 png_composite(w, v, png_ptr->trans[i], back_1.green); | |
2595 palette[i].green = png_ptr->gamma_from_1[w]; | |
2596 | |
2597 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; | |
2598 png_composite(w, v, png_ptr->trans[i], back_1.blue); | |
2599 palette[i].blue = png_ptr->gamma_from_1[w]; | |
2600 } | |
2601 else | |
2602 { | |
2603 palette[i].red = png_ptr->gamma_table[palette[i].red]; | |
2604 palette[i].green = png_ptr->gamma_table[palette[i].green]; | |
2605 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; | |
2606 } | |
2607 } | |
2608 } | |
2609 else | |
2610 { | |
2611 int i; | |
2612 | |
2613 for (i = 0; i < num_palette; i++) | |
2614 { | |
2615 if (palette[i].red == (png_byte)png_ptr->trans_values.gray) | |
2616 { | |
2617 palette[i] = back; | |
2618 } | |
2619 else | |
2620 { | |
2621 palette[i].red = png_ptr->gamma_table[palette[i].red]; | |
2622 palette[i].green = png_ptr->gamma_table[palette[i].green]; | |
2623 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; | |
2624 } | |
2625 } | |
2626 } | |
2627 } | |
2628 else | |
2629 #endif | |
2630 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2631 if (png_ptr->transformations & PNG_GAMMA) | |
2632 { | |
2633 int i; | |
2634 | |
2635 for (i = 0; i < num_palette; i++) | |
2636 { | |
2637 palette[i].red = png_ptr->gamma_table[palette[i].red]; | |
2638 palette[i].green = png_ptr->gamma_table[palette[i].green]; | |
2639 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; | |
2640 } | |
2641 } | |
2642 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2643 else | |
2644 #endif | |
2645 #endif | |
2646 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2647 if (png_ptr->transformations & PNG_BACKGROUND) | |
2648 { | |
2649 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | |
2650 { | |
2651 png_color back; | |
2652 | |
2653 back.red = (png_byte)png_ptr->background.red; | |
2654 back.green = (png_byte)png_ptr->background.green; | |
2655 back.blue = (png_byte)png_ptr->background.blue; | |
2656 | |
2657 for (i = 0; i < (int)png_ptr->num_trans; i++) | |
2658 { | |
2659 if (png_ptr->trans[i] == 0) | |
2660 { | |
2661 palette[i].red = back.red; | |
2662 palette[i].green = back.green; | |
2663 palette[i].blue = back.blue; | |
2664 } | |
2665 else if (png_ptr->trans[i] != 0xff) | |
2666 { | |
2667 png_composite(palette[i].red, png_ptr->palette[i].red, | |
2668 png_ptr->trans[i], back.red); | |
2669 png_composite(palette[i].green, png_ptr->palette[i].green, | |
2670 png_ptr->trans[i], back.green); | |
2671 png_composite(palette[i].blue, png_ptr->palette[i].blue, | |
2672 png_ptr->trans[i], back.blue); | |
2673 } | |
2674 } | |
2675 } | |
2676 else /* assume grayscale palette (what else could it be?) */ | |
2677 { | |
2678 int i; | |
2679 | |
2680 for (i = 0; i < num_palette; i++) | |
2681 { | |
2682 if (i == (png_byte)png_ptr->trans_values.gray) | |
2683 { | |
2684 palette[i].red = (png_byte)png_ptr->background.red; | |
2685 palette[i].green = (png_byte)png_ptr->background.green; | |
2686 palette[i].blue = (png_byte)png_ptr->background.blue; | |
2687 } | |
2688 } | |
2689 } | |
2690 } | |
2691 #endif | |
2692 } | |
2693 #endif | |
2694 | |
2695 #if defined(PNG_READ_BACKGROUND_SUPPORTED) | |
2696 /* Replace any alpha or transparency with the supplied background color. | |
2697 * "background" is already in the screen gamma, while "background_1" is | |
2698 * at a gamma of 1.0. Paletted files have already been taken care of. | |
2699 */ | |
2700 void /* PRIVATE */ | |
2701 png_do_background(png_row_infop row_info, png_bytep row, | |
2702 png_color_16p trans_values, png_color_16p background | |
2703 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2704 , png_color_16p background_1, | |
2705 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, | |
2706 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, | |
2707 png_uint_16pp gamma_16_to_1, int gamma_shift | |
2708 #endif | |
2709 ) | |
2710 { | |
2711 png_bytep sp, dp; | |
2712 png_uint_32 i; | |
2713 png_uint_32 row_width=row_info->width; | |
2714 int shift; | |
2715 | |
2716 png_debug(1, "in png_do_background\n"); | |
2717 if (background != NULL && | |
2718 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
2719 row != NULL && row_info != NULL && | |
2720 #endif | |
2721 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || | |
2722 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) | |
2723 { | |
2724 switch (row_info->color_type) | |
2725 { | |
2726 case PNG_COLOR_TYPE_GRAY: | |
2727 { | |
2728 switch (row_info->bit_depth) | |
2729 { | |
2730 case 1: | |
2731 { | |
2732 sp = row; | |
2733 shift = 7; | |
2734 for (i = 0; i < row_width; i++) | |
2735 { | |
2736 if ((png_uint_16)((*sp >> shift) & 0x01) | |
2737 == trans_values->gray) | |
2738 { | |
2739 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); | |
2740 *sp |= (png_byte)(background->gray << shift); | |
2741 } | |
2742 if (!shift) | |
2743 { | |
2744 shift = 7; | |
2745 sp++; | |
2746 } | |
2747 else | |
2748 shift--; | |
2749 } | |
2750 break; | |
2751 } | |
2752 case 2: | |
2753 { | |
2754 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2755 if (gamma_table != NULL) | |
2756 { | |
2757 sp = row; | |
2758 shift = 6; | |
2759 for (i = 0; i < row_width; i++) | |
2760 { | |
2761 if ((png_uint_16)((*sp >> shift) & 0x03) | |
2762 == trans_values->gray) | |
2763 { | |
2764 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); | |
2765 *sp |= (png_byte)(background->gray << shift); | |
2766 } | |
2767 else | |
2768 { | |
2769 png_byte p = (png_byte)((*sp >> shift) & 0x03); | |
2770 png_byte g = (png_byte)((gamma_table [p | (p << 2) | | |
2771 (p << 4) | (p << 6)] >> 6) & 0x03); | |
2772 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); | |
2773 *sp |= (png_byte)(g << shift); | |
2774 } | |
2775 if (!shift) | |
2776 { | |
2777 shift = 6; | |
2778 sp++; | |
2779 } | |
2780 else | |
2781 shift -= 2; | |
2782 } | |
2783 } | |
2784 else | |
2785 #endif | |
2786 { | |
2787 sp = row; | |
2788 shift = 6; | |
2789 for (i = 0; i < row_width; i++) | |
2790 { | |
2791 if ((png_uint_16)((*sp >> shift) & 0x03) | |
2792 == trans_values->gray) | |
2793 { | |
2794 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); | |
2795 *sp |= (png_byte)(background->gray << shift); | |
2796 } | |
2797 if (!shift) | |
2798 { | |
2799 shift = 6; | |
2800 sp++; | |
2801 } | |
2802 else | |
2803 shift -= 2; | |
2804 } | |
2805 } | |
2806 break; | |
2807 } | |
2808 case 4: | |
2809 { | |
2810 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2811 if (gamma_table != NULL) | |
2812 { | |
2813 sp = row; | |
2814 shift = 4; | |
2815 for (i = 0; i < row_width; i++) | |
2816 { | |
2817 if ((png_uint_16)((*sp >> shift) & 0x0f) | |
2818 == trans_values->gray) | |
2819 { | |
2820 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); | |
2821 *sp |= (png_byte)(background->gray << shift); | |
2822 } | |
2823 else | |
2824 { | |
2825 png_byte p = (png_byte)((*sp >> shift) & 0x0f); | |
2826 png_byte g = (png_byte)((gamma_table[p | | |
2827 (p << 4)] >> 4) & 0x0f); | |
2828 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); | |
2829 *sp |= (png_byte)(g << shift); | |
2830 } | |
2831 if (!shift) | |
2832 { | |
2833 shift = 4; | |
2834 sp++; | |
2835 } | |
2836 else | |
2837 shift -= 4; | |
2838 } | |
2839 } | |
2840 else | |
2841 #endif | |
2842 { | |
2843 sp = row; | |
2844 shift = 4; | |
2845 for (i = 0; i < row_width; i++) | |
2846 { | |
2847 if ((png_uint_16)((*sp >> shift) & 0x0f) | |
2848 == trans_values->gray) | |
2849 { | |
2850 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); | |
2851 *sp |= (png_byte)(background->gray << shift); | |
2852 } | |
2853 if (!shift) | |
2854 { | |
2855 shift = 4; | |
2856 sp++; | |
2857 } | |
2858 else | |
2859 shift -= 4; | |
2860 } | |
2861 } | |
2862 break; | |
2863 } | |
2864 case 8: | |
2865 { | |
2866 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2867 if (gamma_table != NULL) | |
2868 { | |
2869 sp = row; | |
2870 for (i = 0; i < row_width; i++, sp++) | |
2871 { | |
2872 if (*sp == trans_values->gray) | |
2873 { | |
2874 *sp = (png_byte)background->gray; | |
2875 } | |
2876 else | |
2877 { | |
2878 *sp = gamma_table[*sp]; | |
2879 } | |
2880 } | |
2881 } | |
2882 else | |
2883 #endif | |
2884 { | |
2885 sp = row; | |
2886 for (i = 0; i < row_width; i++, sp++) | |
2887 { | |
2888 if (*sp == trans_values->gray) | |
2889 { | |
2890 *sp = (png_byte)background->gray; | |
2891 } | |
2892 } | |
2893 } | |
2894 break; | |
2895 } | |
2896 case 16: | |
2897 { | |
2898 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2899 if (gamma_16 != NULL) | |
2900 { | |
2901 sp = row; | |
2902 for (i = 0; i < row_width; i++, sp += 2) | |
2903 { | |
2904 png_uint_16 v; | |
2905 | |
2906 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); | |
2907 if (v == trans_values->gray) | |
2908 { | |
2909 /* background is already in screen gamma */ | |
2910 *sp = (png_byte)((background->gray >> 8) & 0xff); | |
2911 *(sp + 1) = (png_byte)(background->gray & 0xff); | |
2912 } | |
2913 else | |
2914 { | |
2915 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; | |
2916 *sp = (png_byte)((v >> 8) & 0xff); | |
2917 *(sp + 1) = (png_byte)(v & 0xff); | |
2918 } | |
2919 } | |
2920 } | |
2921 else | |
2922 #endif | |
2923 { | |
2924 sp = row; | |
2925 for (i = 0; i < row_width; i++, sp += 2) | |
2926 { | |
2927 png_uint_16 v; | |
2928 | |
2929 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); | |
2930 if (v == trans_values->gray) | |
2931 { | |
2932 *sp = (png_byte)((background->gray >> 8) & 0xff); | |
2933 *(sp + 1) = (png_byte)(background->gray & 0xff); | |
2934 } | |
2935 } | |
2936 } | |
2937 break; | |
2938 } | |
2939 } | |
2940 break; | |
2941 } | |
2942 case PNG_COLOR_TYPE_RGB: | |
2943 { | |
2944 if (row_info->bit_depth == 8) | |
2945 { | |
2946 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2947 if (gamma_table != NULL) | |
2948 { | |
2949 sp = row; | |
2950 for (i = 0; i < row_width; i++, sp += 3) | |
2951 { | |
2952 if (*sp == trans_values->red && | |
2953 *(sp + 1) == trans_values->green && | |
2954 *(sp + 2) == trans_values->blue) | |
2955 { | |
2956 *sp = (png_byte)background->red; | |
2957 *(sp + 1) = (png_byte)background->green; | |
2958 *(sp + 2) = (png_byte)background->blue; | |
2959 } | |
2960 else | |
2961 { | |
2962 *sp = gamma_table[*sp]; | |
2963 *(sp + 1) = gamma_table[*(sp + 1)]; | |
2964 *(sp + 2) = gamma_table[*(sp + 2)]; | |
2965 } | |
2966 } | |
2967 } | |
2968 else | |
2969 #endif | |
2970 { | |
2971 sp = row; | |
2972 for (i = 0; i < row_width; i++, sp += 3) | |
2973 { | |
2974 if (*sp == trans_values->red && | |
2975 *(sp + 1) == trans_values->green && | |
2976 *(sp + 2) == trans_values->blue) | |
2977 { | |
2978 *sp = (png_byte)background->red; | |
2979 *(sp + 1) = (png_byte)background->green; | |
2980 *(sp + 2) = (png_byte)background->blue; | |
2981 } | |
2982 } | |
2983 } | |
2984 } | |
2985 else /* if (row_info->bit_depth == 16) */ | |
2986 { | |
2987 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
2988 if (gamma_16 != NULL) | |
2989 { | |
2990 sp = row; | |
2991 for (i = 0; i < row_width; i++, sp += 6) | |
2992 { | |
2993 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); | |
2994 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); | |
2995 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); | |
2996 if (r == trans_values->red && g == trans_values->green && | |
2997 b == trans_values->blue) | |
2998 { | |
2999 /* background is already in screen gamma */ | |
3000 *sp = (png_byte)((background->red >> 8) & 0xff); | |
3001 *(sp + 1) = (png_byte)(background->red & 0xff); | |
3002 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); | |
3003 *(sp + 3) = (png_byte)(background->green & 0xff); | |
3004 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); | |
3005 *(sp + 5) = (png_byte)(background->blue & 0xff); | |
3006 } | |
3007 else | |
3008 { | |
3009 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; | |
3010 *sp = (png_byte)((v >> 8) & 0xff); | |
3011 *(sp + 1) = (png_byte)(v & 0xff); | |
3012 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; | |
3013 *(sp + 2) = (png_byte)((v >> 8) & 0xff); | |
3014 *(sp + 3) = (png_byte)(v & 0xff); | |
3015 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; | |
3016 *(sp + 4) = (png_byte)((v >> 8) & 0xff); | |
3017 *(sp + 5) = (png_byte)(v & 0xff); | |
3018 } | |
3019 } | |
3020 } | |
3021 else | |
3022 #endif | |
3023 { | |
3024 sp = row; | |
3025 for (i = 0; i < row_width; i++, sp += 6) | |
3026 { | |
3027 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); | |
3028 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); | |
3029 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); | |
3030 | |
3031 if (r == trans_values->red && g == trans_values->green && | |
3032 b == trans_values->blue) | |
3033 { | |
3034 *sp = (png_byte)((background->red >> 8) & 0xff); | |
3035 *(sp + 1) = (png_byte)(background->red & 0xff); | |
3036 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); | |
3037 *(sp + 3) = (png_byte)(background->green & 0xff); | |
3038 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); | |
3039 *(sp + 5) = (png_byte)(background->blue & 0xff); | |
3040 } | |
3041 } | |
3042 } | |
3043 } | |
3044 break; | |
3045 } | |
3046 case PNG_COLOR_TYPE_GRAY_ALPHA: | |
3047 { | |
3048 if (row_info->bit_depth == 8) | |
3049 { | |
3050 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3051 if (gamma_to_1 != NULL && gamma_from_1 != NULL && | |
3052 gamma_table != NULL) | |
3053 { | |
3054 sp = row; | |
3055 dp = row; | |
3056 for (i = 0; i < row_width; i++, sp += 2, dp++) | |
3057 { | |
3058 png_uint_16 a = *(sp + 1); | |
3059 | |
3060 if (a == 0xff) | |
3061 { | |
3062 *dp = gamma_table[*sp]; | |
3063 } | |
3064 else if (a == 0) | |
3065 { | |
3066 /* background is already in screen gamma */ | |
3067 *dp = (png_byte)background->gray; | |
3068 } | |
3069 else | |
3070 { | |
3071 png_byte v, w; | |
3072 | |
3073 v = gamma_to_1[*sp]; | |
3074 png_composite(w, v, a, background_1->gray); | |
3075 *dp = gamma_from_1[w]; | |
3076 } | |
3077 } | |
3078 } | |
3079 else | |
3080 #endif | |
3081 { | |
3082 sp = row; | |
3083 dp = row; | |
3084 for (i = 0; i < row_width; i++, sp += 2, dp++) | |
3085 { | |
3086 png_byte a = *(sp + 1); | |
3087 | |
3088 if (a == 0xff) | |
3089 { | |
3090 *dp = *sp; | |
3091 } | |
3092 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3093 else if (a == 0) | |
3094 { | |
3095 *dp = (png_byte)background->gray; | |
3096 } | |
3097 else | |
3098 { | |
3099 png_composite(*dp, *sp, a, background_1->gray); | |
3100 } | |
3101 #else | |
3102 *dp = (png_byte)background->gray; | |
3103 #endif | |
3104 } | |
3105 } | |
3106 } | |
3107 else /* if (png_ptr->bit_depth == 16) */ | |
3108 { | |
3109 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3110 if (gamma_16 != NULL && gamma_16_from_1 != NULL && | |
3111 gamma_16_to_1 != NULL) | |
3112 { | |
3113 sp = row; | |
3114 dp = row; | |
3115 for (i = 0; i < row_width; i++, sp += 4, dp += 2) | |
3116 { | |
3117 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); | |
3118 | |
3119 if (a == (png_uint_16)0xffff) | |
3120 { | |
3121 png_uint_16 v; | |
3122 | |
3123 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; | |
3124 *dp = (png_byte)((v >> 8) & 0xff); | |
3125 *(dp + 1) = (png_byte)(v & 0xff); | |
3126 } | |
3127 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3128 else if (a == 0) | |
3129 #else | |
3130 else | |
3131 #endif | |
3132 { | |
3133 /* background is already in screen gamma */ | |
3134 *dp = (png_byte)((background->gray >> 8) & 0xff); | |
3135 *(dp + 1) = (png_byte)(background->gray & 0xff); | |
3136 } | |
3137 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3138 else | |
3139 { | |
3140 png_uint_16 g, v, w; | |
3141 | |
3142 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; | |
3143 png_composite_16(v, g, a, background_1->gray); | |
3144 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; | |
3145 *dp = (png_byte)((w >> 8) & 0xff); | |
3146 *(dp + 1) = (png_byte)(w & 0xff); | |
3147 } | |
3148 #endif | |
3149 } | |
3150 } | |
3151 else | |
3152 #endif | |
3153 { | |
3154 sp = row; | |
3155 dp = row; | |
3156 for (i = 0; i < row_width; i++, sp += 4, dp += 2) | |
3157 { | |
3158 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); | |
3159 if (a == (png_uint_16)0xffff) | |
3160 { | |
3161 png_memcpy(dp, sp, 2); | |
3162 } | |
3163 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3164 else if (a == 0) | |
3165 #else | |
3166 else | |
3167 #endif | |
3168 { | |
3169 *dp = (png_byte)((background->gray >> 8) & 0xff); | |
3170 *(dp + 1) = (png_byte)(background->gray & 0xff); | |
3171 } | |
3172 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3173 else | |
3174 { | |
3175 png_uint_16 g, v; | |
3176 | |
3177 g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); | |
3178 png_composite_16(v, g, a, background_1->gray); | |
3179 *dp = (png_byte)((v >> 8) & 0xff); | |
3180 *(dp + 1) = (png_byte)(v & 0xff); | |
3181 } | |
3182 #endif | |
3183 } | |
3184 } | |
3185 } | |
3186 break; | |
3187 } | |
3188 case PNG_COLOR_TYPE_RGB_ALPHA: | |
3189 { | |
3190 if (row_info->bit_depth == 8) | |
3191 { | |
3192 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3193 if (gamma_to_1 != NULL && gamma_from_1 != NULL && | |
3194 gamma_table != NULL) | |
3195 { | |
3196 sp = row; | |
3197 dp = row; | |
3198 for (i = 0; i < row_width; i++, sp += 4, dp += 3) | |
3199 { | |
3200 png_byte a = *(sp + 3); | |
3201 | |
3202 if (a == 0xff) | |
3203 { | |
3204 *dp = gamma_table[*sp]; | |
3205 *(dp + 1) = gamma_table[*(sp + 1)]; | |
3206 *(dp + 2) = gamma_table[*(sp + 2)]; | |
3207 } | |
3208 else if (a == 0) | |
3209 { | |
3210 /* background is already in screen gamma */ | |
3211 *dp = (png_byte)background->red; | |
3212 *(dp + 1) = (png_byte)background->green; | |
3213 *(dp + 2) = (png_byte)background->blue; | |
3214 } | |
3215 else | |
3216 { | |
3217 png_byte v, w; | |
3218 | |
3219 v = gamma_to_1[*sp]; | |
3220 png_composite(w, v, a, background_1->red); | |
3221 *dp = gamma_from_1[w]; | |
3222 v = gamma_to_1[*(sp + 1)]; | |
3223 png_composite(w, v, a, background_1->green); | |
3224 *(dp + 1) = gamma_from_1[w]; | |
3225 v = gamma_to_1[*(sp + 2)]; | |
3226 png_composite(w, v, a, background_1->blue); | |
3227 *(dp + 2) = gamma_from_1[w]; | |
3228 } | |
3229 } | |
3230 } | |
3231 else | |
3232 #endif | |
3233 { | |
3234 sp = row; | |
3235 dp = row; | |
3236 for (i = 0; i < row_width; i++, sp += 4, dp += 3) | |
3237 { | |
3238 png_byte a = *(sp + 3); | |
3239 | |
3240 if (a == 0xff) | |
3241 { | |
3242 *dp = *sp; | |
3243 *(dp + 1) = *(sp + 1); | |
3244 *(dp + 2) = *(sp + 2); | |
3245 } | |
3246 else if (a == 0) | |
3247 { | |
3248 *dp = (png_byte)background->red; | |
3249 *(dp + 1) = (png_byte)background->green; | |
3250 *(dp + 2) = (png_byte)background->blue; | |
3251 } | |
3252 else | |
3253 { | |
3254 png_composite(*dp, *sp, a, background->red); | |
3255 png_composite(*(dp + 1), *(sp + 1), a, | |
3256 background->green); | |
3257 png_composite(*(dp + 2), *(sp + 2), a, | |
3258 background->blue); | |
3259 } | |
3260 } | |
3261 } | |
3262 } | |
3263 else /* if (row_info->bit_depth == 16) */ | |
3264 { | |
3265 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3266 if (gamma_16 != NULL && gamma_16_from_1 != NULL && | |
3267 gamma_16_to_1 != NULL) | |
3268 { | |
3269 sp = row; | |
3270 dp = row; | |
3271 for (i = 0; i < row_width; i++, sp += 8, dp += 6) | |
3272 { | |
3273 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) | |
3274 << 8) + (png_uint_16)(*(sp + 7))); | |
3275 if (a == (png_uint_16)0xffff) | |
3276 { | |
3277 png_uint_16 v; | |
3278 | |
3279 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; | |
3280 *dp = (png_byte)((v >> 8) & 0xff); | |
3281 *(dp + 1) = (png_byte)(v & 0xff); | |
3282 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; | |
3283 *(dp + 2) = (png_byte)((v >> 8) & 0xff); | |
3284 *(dp + 3) = (png_byte)(v & 0xff); | |
3285 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; | |
3286 *(dp + 4) = (png_byte)((v >> 8) & 0xff); | |
3287 *(dp + 5) = (png_byte)(v & 0xff); | |
3288 } | |
3289 else if (a == 0) | |
3290 { | |
3291 /* background is already in screen gamma */ | |
3292 *dp = (png_byte)((background->red >> 8) & 0xff); | |
3293 *(dp + 1) = (png_byte)(background->red & 0xff); | |
3294 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); | |
3295 *(dp + 3) = (png_byte)(background->green & 0xff); | |
3296 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); | |
3297 *(dp + 5) = (png_byte)(background->blue & 0xff); | |
3298 } | |
3299 else | |
3300 { | |
3301 png_uint_16 v, w, x; | |
3302 | |
3303 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; | |
3304 png_composite_16(w, v, a, background_1->red); | |
3305 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; | |
3306 *dp = (png_byte)((x >> 8) & 0xff); | |
3307 *(dp + 1) = (png_byte)(x & 0xff); | |
3308 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; | |
3309 png_composite_16(w, v, a, background_1->green); | |
3310 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; | |
3311 *(dp + 2) = (png_byte)((x >> 8) & 0xff); | |
3312 *(dp + 3) = (png_byte)(x & 0xff); | |
3313 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; | |
3314 png_composite_16(w, v, a, background_1->blue); | |
3315 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; | |
3316 *(dp + 4) = (png_byte)((x >> 8) & 0xff); | |
3317 *(dp + 5) = (png_byte)(x & 0xff); | |
3318 } | |
3319 } | |
3320 } | |
3321 else | |
3322 #endif | |
3323 { | |
3324 sp = row; | |
3325 dp = row; | |
3326 for (i = 0; i < row_width; i++, sp += 8, dp += 6) | |
3327 { | |
3328 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) | |
3329 << 8) + (png_uint_16)(*(sp + 7))); | |
3330 if (a == (png_uint_16)0xffff) | |
3331 { | |
3332 png_memcpy(dp, sp, 6); | |
3333 } | |
3334 else if (a == 0) | |
3335 { | |
3336 *dp = (png_byte)((background->red >> 8) & 0xff); | |
3337 *(dp + 1) = (png_byte)(background->red & 0xff); | |
3338 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); | |
3339 *(dp + 3) = (png_byte)(background->green & 0xff); | |
3340 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); | |
3341 *(dp + 5) = (png_byte)(background->blue & 0xff); | |
3342 } | |
3343 else | |
3344 { | |
3345 png_uint_16 v; | |
3346 | |
3347 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); | |
3348 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) | |
3349 + *(sp + 3)); | |
3350 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) | |
3351 + *(sp + 5)); | |
3352 | |
3353 png_composite_16(v, r, a, background->red); | |
3354 *dp = (png_byte)((v >> 8) & 0xff); | |
3355 *(dp + 1) = (png_byte)(v & 0xff); | |
3356 png_composite_16(v, g, a, background->green); | |
3357 *(dp + 2) = (png_byte)((v >> 8) & 0xff); | |
3358 *(dp + 3) = (png_byte)(v & 0xff); | |
3359 png_composite_16(v, b, a, background->blue); | |
3360 *(dp + 4) = (png_byte)((v >> 8) & 0xff); | |
3361 *(dp + 5) = (png_byte)(v & 0xff); | |
3362 } | |
3363 } | |
3364 } | |
3365 } | |
3366 break; | |
3367 } | |
3368 } | |
3369 | |
3370 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) | |
3371 { | |
3372 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; | |
3373 row_info->channels--; | |
3374 row_info->pixel_depth = (png_byte)(row_info->channels * | |
3375 row_info->bit_depth); | |
3376 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
3377 } | |
3378 } | |
3379 } | |
3380 #endif | |
3381 | |
3382 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
3383 /* Gamma correct the image, avoiding the alpha channel. Make sure | |
3384 * you do this after you deal with the transparency issue on grayscale | |
3385 * or RGB images. If your bit depth is 8, use gamma_table, if it | |
3386 * is 16, use gamma_16_table and gamma_shift. Build these with | |
3387 * build_gamma_table(). | |
3388 */ | |
3389 void /* PRIVATE */ | |
3390 png_do_gamma(png_row_infop row_info, png_bytep row, | |
3391 png_bytep gamma_table, png_uint_16pp gamma_16_table, | |
3392 int gamma_shift) | |
3393 { | |
3394 png_bytep sp; | |
3395 png_uint_32 i; | |
3396 png_uint_32 row_width=row_info->width; | |
3397 | |
3398 png_debug(1, "in png_do_gamma\n"); | |
3399 if ( | |
3400 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
3401 row != NULL && row_info != NULL && | |
3402 #endif | |
3403 ((row_info->bit_depth <= 8 && gamma_table != NULL) || | |
3404 (row_info->bit_depth == 16 && gamma_16_table != NULL))) | |
3405 { | |
3406 switch (row_info->color_type) | |
3407 { | |
3408 case PNG_COLOR_TYPE_RGB: | |
3409 { | |
3410 if (row_info->bit_depth == 8) | |
3411 { | |
3412 sp = row; | |
3413 for (i = 0; i < row_width; i++) | |
3414 { | |
3415 *sp = gamma_table[*sp]; | |
3416 sp++; | |
3417 *sp = gamma_table[*sp]; | |
3418 sp++; | |
3419 *sp = gamma_table[*sp]; | |
3420 sp++; | |
3421 } | |
3422 } | |
3423 else /* if (row_info->bit_depth == 16) */ | |
3424 { | |
3425 sp = row; | |
3426 for (i = 0; i < row_width; i++) | |
3427 { | |
3428 png_uint_16 v; | |
3429 | |
3430 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3431 *sp = (png_byte)((v >> 8) & 0xff); | |
3432 *(sp + 1) = (png_byte)(v & 0xff); | |
3433 sp += 2; | |
3434 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3435 *sp = (png_byte)((v >> 8) & 0xff); | |
3436 *(sp + 1) = (png_byte)(v & 0xff); | |
3437 sp += 2; | |
3438 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3439 *sp = (png_byte)((v >> 8) & 0xff); | |
3440 *(sp + 1) = (png_byte)(v & 0xff); | |
3441 sp += 2; | |
3442 } | |
3443 } | |
3444 break; | |
3445 } | |
3446 case PNG_COLOR_TYPE_RGB_ALPHA: | |
3447 { | |
3448 if (row_info->bit_depth == 8) | |
3449 { | |
3450 sp = row; | |
3451 for (i = 0; i < row_width; i++) | |
3452 { | |
3453 *sp = gamma_table[*sp]; | |
3454 sp++; | |
3455 *sp = gamma_table[*sp]; | |
3456 sp++; | |
3457 *sp = gamma_table[*sp]; | |
3458 sp++; | |
3459 sp++; | |
3460 } | |
3461 } | |
3462 else /* if (row_info->bit_depth == 16) */ | |
3463 { | |
3464 sp = row; | |
3465 for (i = 0; i < row_width; i++) | |
3466 { | |
3467 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3468 *sp = (png_byte)((v >> 8) & 0xff); | |
3469 *(sp + 1) = (png_byte)(v & 0xff); | |
3470 sp += 2; | |
3471 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3472 *sp = (png_byte)((v >> 8) & 0xff); | |
3473 *(sp + 1) = (png_byte)(v & 0xff); | |
3474 sp += 2; | |
3475 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3476 *sp = (png_byte)((v >> 8) & 0xff); | |
3477 *(sp + 1) = (png_byte)(v & 0xff); | |
3478 sp += 4; | |
3479 } | |
3480 } | |
3481 break; | |
3482 } | |
3483 case PNG_COLOR_TYPE_GRAY_ALPHA: | |
3484 { | |
3485 if (row_info->bit_depth == 8) | |
3486 { | |
3487 sp = row; | |
3488 for (i = 0; i < row_width; i++) | |
3489 { | |
3490 *sp = gamma_table[*sp]; | |
3491 sp += 2; | |
3492 } | |
3493 } | |
3494 else /* if (row_info->bit_depth == 16) */ | |
3495 { | |
3496 sp = row; | |
3497 for (i = 0; i < row_width; i++) | |
3498 { | |
3499 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3500 *sp = (png_byte)((v >> 8) & 0xff); | |
3501 *(sp + 1) = (png_byte)(v & 0xff); | |
3502 sp += 4; | |
3503 } | |
3504 } | |
3505 break; | |
3506 } | |
3507 case PNG_COLOR_TYPE_GRAY: | |
3508 { | |
3509 if (row_info->bit_depth == 2) | |
3510 { | |
3511 sp = row; | |
3512 for (i = 0; i < row_width; i += 4) | |
3513 { | |
3514 int a = *sp & 0xc0; | |
3515 int b = *sp & 0x30; | |
3516 int c = *sp & 0x0c; | |
3517 int d = *sp & 0x03; | |
3518 | |
3519 *sp = (png_byte)( | |
3520 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| | |
3521 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| | |
3522 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| | |
3523 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); | |
3524 sp++; | |
3525 } | |
3526 } | |
3527 if (row_info->bit_depth == 4) | |
3528 { | |
3529 sp = row; | |
3530 for (i = 0; i < row_width; i += 2) | |
3531 { | |
3532 int msb = *sp & 0xf0; | |
3533 int lsb = *sp & 0x0f; | |
3534 | |
3535 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) | |
3536 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); | |
3537 sp++; | |
3538 } | |
3539 } | |
3540 else if (row_info->bit_depth == 8) | |
3541 { | |
3542 sp = row; | |
3543 for (i = 0; i < row_width; i++) | |
3544 { | |
3545 *sp = gamma_table[*sp]; | |
3546 sp++; | |
3547 } | |
3548 } | |
3549 else if (row_info->bit_depth == 16) | |
3550 { | |
3551 sp = row; | |
3552 for (i = 0; i < row_width; i++) | |
3553 { | |
3554 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; | |
3555 *sp = (png_byte)((v >> 8) & 0xff); | |
3556 *(sp + 1) = (png_byte)(v & 0xff); | |
3557 sp += 2; | |
3558 } | |
3559 } | |
3560 break; | |
3561 } | |
3562 } | |
3563 } | |
3564 } | |
3565 #endif | |
3566 | |
3567 #if defined(PNG_READ_EXPAND_SUPPORTED) | |
3568 /* Expands a palette row to an RGB or RGBA row depending | |
3569 * upon whether you supply trans and num_trans. | |
3570 */ | |
3571 void /* PRIVATE */ | |
3572 png_do_expand_palette(png_row_infop row_info, png_bytep row, | |
3573 png_colorp palette, png_bytep trans, int num_trans) | |
3574 { | |
3575 int shift, value; | |
3576 png_bytep sp, dp; | |
3577 png_uint_32 i; | |
3578 png_uint_32 row_width=row_info->width; | |
3579 | |
3580 png_debug(1, "in png_do_expand_palette\n"); | |
3581 if ( | |
3582 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
3583 row != NULL && row_info != NULL && | |
3584 #endif | |
3585 row_info->color_type == PNG_COLOR_TYPE_PALETTE) | |
3586 { | |
3587 if (row_info->bit_depth < 8) | |
3588 { | |
3589 switch (row_info->bit_depth) | |
3590 { | |
3591 case 1: | |
3592 { | |
3593 sp = row + (png_size_t)((row_width - 1) >> 3); | |
3594 dp = row + (png_size_t)row_width - 1; | |
3595 shift = 7 - (int)((row_width + 7) & 0x07); | |
3596 for (i = 0; i < row_width; i++) | |
3597 { | |
3598 if ((*sp >> shift) & 0x01) | |
3599 *dp = 1; | |
3600 else | |
3601 *dp = 0; | |
3602 if (shift == 7) | |
3603 { | |
3604 shift = 0; | |
3605 sp--; | |
3606 } | |
3607 else | |
3608 shift++; | |
3609 | |
3610 dp--; | |
3611 } | |
3612 break; | |
3613 } | |
3614 case 2: | |
3615 { | |
3616 sp = row + (png_size_t)((row_width - 1) >> 2); | |
3617 dp = row + (png_size_t)row_width - 1; | |
3618 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); | |
3619 for (i = 0; i < row_width; i++) | |
3620 { | |
3621 value = (*sp >> shift) & 0x03; | |
3622 *dp = (png_byte)value; | |
3623 if (shift == 6) | |
3624 { | |
3625 shift = 0; | |
3626 sp--; | |
3627 } | |
3628 else | |
3629 shift += 2; | |
3630 | |
3631 dp--; | |
3632 } | |
3633 break; | |
3634 } | |
3635 case 4: | |
3636 { | |
3637 sp = row + (png_size_t)((row_width - 1) >> 1); | |
3638 dp = row + (png_size_t)row_width - 1; | |
3639 shift = (int)((row_width & 0x01) << 2); | |
3640 for (i = 0; i < row_width; i++) | |
3641 { | |
3642 value = (*sp >> shift) & 0x0f; | |
3643 *dp = (png_byte)value; | |
3644 if (shift == 4) | |
3645 { | |
3646 shift = 0; | |
3647 sp--; | |
3648 } | |
3649 else | |
3650 shift += 4; | |
3651 | |
3652 dp--; | |
3653 } | |
3654 break; | |
3655 } | |
3656 } | |
3657 row_info->bit_depth = 8; | |
3658 row_info->pixel_depth = 8; | |
3659 row_info->rowbytes = row_width; | |
3660 } | |
3661 switch (row_info->bit_depth) | |
3662 { | |
3663 case 8: | |
3664 { | |
3665 if (trans != NULL) | |
3666 { | |
3667 sp = row + (png_size_t)row_width - 1; | |
3668 dp = row + (png_size_t)(row_width << 2) - 1; | |
3669 | |
3670 for (i = 0; i < row_width; i++) | |
3671 { | |
3672 if ((int)(*sp) >= num_trans) | |
3673 *dp-- = 0xff; | |
3674 else | |
3675 *dp-- = trans[*sp]; | |
3676 *dp-- = palette[*sp].blue; | |
3677 *dp-- = palette[*sp].green; | |
3678 *dp-- = palette[*sp].red; | |
3679 sp--; | |
3680 } | |
3681 row_info->bit_depth = 8; | |
3682 row_info->pixel_depth = 32; | |
3683 row_info->rowbytes = row_width * 4; | |
3684 row_info->color_type = 6; | |
3685 row_info->channels = 4; | |
3686 } | |
3687 else | |
3688 { | |
3689 sp = row + (png_size_t)row_width - 1; | |
3690 dp = row + (png_size_t)(row_width * 3) - 1; | |
3691 | |
3692 for (i = 0; i < row_width; i++) | |
3693 { | |
3694 *dp-- = palette[*sp].blue; | |
3695 *dp-- = palette[*sp].green; | |
3696 *dp-- = palette[*sp].red; | |
3697 sp--; | |
3698 } | |
3699 row_info->bit_depth = 8; | |
3700 row_info->pixel_depth = 24; | |
3701 row_info->rowbytes = row_width * 3; | |
3702 row_info->color_type = 2; | |
3703 row_info->channels = 3; | |
3704 } | |
3705 break; | |
3706 } | |
3707 } | |
3708 } | |
3709 } | |
3710 | |
3711 /* If the bit depth < 8, it is expanded to 8. Also, if the already | |
3712 * expanded transparency value is supplied, an alpha channel is built. | |
3713 */ | |
3714 void /* PRIVATE */ | |
3715 png_do_expand(png_row_infop row_info, png_bytep row, | |
3716 png_color_16p trans_value) | |
3717 { | |
3718 int shift, value; | |
3719 png_bytep sp, dp; | |
3720 png_uint_32 i; | |
3721 png_uint_32 row_width=row_info->width; | |
3722 | |
3723 png_debug(1, "in png_do_expand\n"); | |
3724 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
3725 if (row != NULL && row_info != NULL) | |
3726 #endif | |
3727 { | |
3728 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) | |
3729 { | |
3730 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); | |
3731 | |
3732 if (row_info->bit_depth < 8) | |
3733 { | |
3734 switch (row_info->bit_depth) | |
3735 { | |
3736 case 1: | |
3737 { | |
3738 gray = (png_uint_16)((gray&0x01)*0xff); | |
3739 sp = row + (png_size_t)((row_width - 1) >> 3); | |
3740 dp = row + (png_size_t)row_width - 1; | |
3741 shift = 7 - (int)((row_width + 7) & 0x07); | |
3742 for (i = 0; i < row_width; i++) | |
3743 { | |
3744 if ((*sp >> shift) & 0x01) | |
3745 *dp = 0xff; | |
3746 else | |
3747 *dp = 0; | |
3748 if (shift == 7) | |
3749 { | |
3750 shift = 0; | |
3751 sp--; | |
3752 } | |
3753 else | |
3754 shift++; | |
3755 | |
3756 dp--; | |
3757 } | |
3758 break; | |
3759 } | |
3760 case 2: | |
3761 { | |
3762 gray = (png_uint_16)((gray&0x03)*0x55); | |
3763 sp = row + (png_size_t)((row_width - 1) >> 2); | |
3764 dp = row + (png_size_t)row_width - 1; | |
3765 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); | |
3766 for (i = 0; i < row_width; i++) | |
3767 { | |
3768 value = (*sp >> shift) & 0x03; | |
3769 *dp = (png_byte)(value | (value << 2) | (value << 4) | | |
3770 (value << 6)); | |
3771 if (shift == 6) | |
3772 { | |
3773 shift = 0; | |
3774 sp--; | |
3775 } | |
3776 else | |
3777 shift += 2; | |
3778 | |
3779 dp--; | |
3780 } | |
3781 break; | |
3782 } | |
3783 case 4: | |
3784 { | |
3785 gray = (png_uint_16)((gray&0x0f)*0x11); | |
3786 sp = row + (png_size_t)((row_width - 1) >> 1); | |
3787 dp = row + (png_size_t)row_width - 1; | |
3788 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); | |
3789 for (i = 0; i < row_width; i++) | |
3790 { | |
3791 value = (*sp >> shift) & 0x0f; | |
3792 *dp = (png_byte)(value | (value << 4)); | |
3793 if (shift == 4) | |
3794 { | |
3795 shift = 0; | |
3796 sp--; | |
3797 } | |
3798 else | |
3799 shift = 4; | |
3800 | |
3801 dp--; | |
3802 } | |
3803 break; | |
3804 } | |
3805 } | |
3806 row_info->bit_depth = 8; | |
3807 row_info->pixel_depth = 8; | |
3808 row_info->rowbytes = row_width; | |
3809 } | |
3810 | |
3811 if (trans_value != NULL) | |
3812 { | |
3813 if (row_info->bit_depth == 8) | |
3814 { | |
3815 gray = gray & 0xff; | |
3816 sp = row + (png_size_t)row_width - 1; | |
3817 dp = row + (png_size_t)(row_width << 1) - 1; | |
3818 for (i = 0; i < row_width; i++) | |
3819 { | |
3820 if (*sp == gray) | |
3821 *dp-- = 0; | |
3822 else | |
3823 *dp-- = 0xff; | |
3824 *dp-- = *sp--; | |
3825 } | |
3826 } | |
3827 else if (row_info->bit_depth == 16) | |
3828 { | |
3829 png_byte gray_high = (gray >> 8) & 0xff; | |
3830 png_byte gray_low = gray & 0xff; | |
3831 sp = row + row_info->rowbytes - 1; | |
3832 dp = row + (row_info->rowbytes << 1) - 1; | |
3833 for (i = 0; i < row_width; i++) | |
3834 { | |
3835 if (*(sp-1) == gray_high && *(sp) == gray_low) | |
3836 { | |
3837 *dp-- = 0; | |
3838 *dp-- = 0; | |
3839 } | |
3840 else | |
3841 { | |
3842 *dp-- = 0xff; | |
3843 *dp-- = 0xff; | |
3844 } | |
3845 *dp-- = *sp--; | |
3846 *dp-- = *sp--; | |
3847 } | |
3848 } | |
3849 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; | |
3850 row_info->channels = 2; | |
3851 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); | |
3852 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, | |
3853 row_width); | |
3854 } | |
3855 } | |
3856 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) | |
3857 { | |
3858 if (row_info->bit_depth == 8) | |
3859 { | |
3860 png_byte red = trans_value->red & 0xff; | |
3861 png_byte green = trans_value->green & 0xff; | |
3862 png_byte blue = trans_value->blue & 0xff; | |
3863 sp = row + (png_size_t)row_info->rowbytes - 1; | |
3864 dp = row + (png_size_t)(row_width << 2) - 1; | |
3865 for (i = 0; i < row_width; i++) | |
3866 { | |
3867 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) | |
3868 *dp-- = 0; | |
3869 else | |
3870 *dp-- = 0xff; | |
3871 *dp-- = *sp--; | |
3872 *dp-- = *sp--; | |
3873 *dp-- = *sp--; | |
3874 } | |
3875 } | |
3876 else if (row_info->bit_depth == 16) | |
3877 { | |
3878 png_byte red_high = (trans_value->red >> 8) & 0xff; | |
3879 png_byte green_high = (trans_value->green >> 8) & 0xff; | |
3880 png_byte blue_high = (trans_value->blue >> 8) & 0xff; | |
3881 png_byte red_low = trans_value->red & 0xff; | |
3882 png_byte green_low = trans_value->green & 0xff; | |
3883 png_byte blue_low = trans_value->blue & 0xff; | |
3884 sp = row + row_info->rowbytes - 1; | |
3885 dp = row + (png_size_t)(row_width << 3) - 1; | |
3886 for (i = 0; i < row_width; i++) | |
3887 { | |
3888 if (*(sp - 5) == red_high && | |
3889 *(sp - 4) == red_low && | |
3890 *(sp - 3) == green_high && | |
3891 *(sp - 2) == green_low && | |
3892 *(sp - 1) == blue_high && | |
3893 *(sp ) == blue_low) | |
3894 { | |
3895 *dp-- = 0; | |
3896 *dp-- = 0; | |
3897 } | |
3898 else | |
3899 { | |
3900 *dp-- = 0xff; | |
3901 *dp-- = 0xff; | |
3902 } | |
3903 *dp-- = *sp--; | |
3904 *dp-- = *sp--; | |
3905 *dp-- = *sp--; | |
3906 *dp-- = *sp--; | |
3907 *dp-- = *sp--; | |
3908 *dp-- = *sp--; | |
3909 } | |
3910 } | |
3911 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; | |
3912 row_info->channels = 4; | |
3913 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); | |
3914 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
3915 } | |
3916 } | |
3917 } | |
3918 #endif | |
3919 | |
3920 #if defined(PNG_READ_DITHER_SUPPORTED) | |
3921 void /* PRIVATE */ | |
3922 png_do_dither(png_row_infop row_info, png_bytep row, | |
3923 png_bytep palette_lookup, png_bytep dither_lookup) | |
3924 { | |
3925 png_bytep sp, dp; | |
3926 png_uint_32 i; | |
3927 png_uint_32 row_width=row_info->width; | |
3928 | |
3929 png_debug(1, "in png_do_dither\n"); | |
3930 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
3931 if (row != NULL && row_info != NULL) | |
3932 #endif | |
3933 { | |
3934 if (row_info->color_type == PNG_COLOR_TYPE_RGB && | |
3935 palette_lookup && row_info->bit_depth == 8) | |
3936 { | |
3937 int r, g, b, p; | |
3938 sp = row; | |
3939 dp = row; | |
3940 for (i = 0; i < row_width; i++) | |
3941 { | |
3942 r = *sp++; | |
3943 g = *sp++; | |
3944 b = *sp++; | |
3945 | |
3946 /* this looks real messy, but the compiler will reduce | |
3947 it down to a reasonable formula. For example, with | |
3948 5 bits per color, we get: | |
3949 p = (((r >> 3) & 0x1f) << 10) | | |
3950 (((g >> 3) & 0x1f) << 5) | | |
3951 ((b >> 3) & 0x1f); | |
3952 */ | |
3953 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & | |
3954 ((1 << PNG_DITHER_RED_BITS) - 1)) << | |
3955 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | | |
3956 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & | |
3957 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << | |
3958 (PNG_DITHER_BLUE_BITS)) | | |
3959 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & | |
3960 ((1 << PNG_DITHER_BLUE_BITS) - 1)); | |
3961 | |
3962 *dp++ = palette_lookup[p]; | |
3963 } | |
3964 row_info->color_type = PNG_COLOR_TYPE_PALETTE; | |
3965 row_info->channels = 1; | |
3966 row_info->pixel_depth = row_info->bit_depth; | |
3967 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
3968 } | |
3969 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && | |
3970 palette_lookup != NULL && row_info->bit_depth == 8) | |
3971 { | |
3972 int r, g, b, p; | |
3973 sp = row; | |
3974 dp = row; | |
3975 for (i = 0; i < row_width; i++) | |
3976 { | |
3977 r = *sp++; | |
3978 g = *sp++; | |
3979 b = *sp++; | |
3980 sp++; | |
3981 | |
3982 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & | |
3983 ((1 << PNG_DITHER_RED_BITS) - 1)) << | |
3984 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | | |
3985 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & | |
3986 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << | |
3987 (PNG_DITHER_BLUE_BITS)) | | |
3988 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & | |
3989 ((1 << PNG_DITHER_BLUE_BITS) - 1)); | |
3990 | |
3991 *dp++ = palette_lookup[p]; | |
3992 } | |
3993 row_info->color_type = PNG_COLOR_TYPE_PALETTE; | |
3994 row_info->channels = 1; | |
3995 row_info->pixel_depth = row_info->bit_depth; | |
3996 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); | |
3997 } | |
3998 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && | |
3999 dither_lookup && row_info->bit_depth == 8) | |
4000 { | |
4001 sp = row; | |
4002 for (i = 0; i < row_width; i++, sp++) | |
4003 { | |
4004 *sp = dither_lookup[*sp]; | |
4005 } | |
4006 } | |
4007 } | |
4008 } | |
4009 #endif | |
4010 | |
4011 #ifdef PNG_FLOATING_POINT_SUPPORTED | |
4012 #if defined(PNG_READ_GAMMA_SUPPORTED) | |
4013 static PNG_CONST int png_gamma_shift[] = | |
4014 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; | |
4015 | |
4016 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit | |
4017 * tables, we don't make a full table if we are reducing to 8-bit in | |
4018 * the future. Note also how the gamma_16 tables are segmented so that | |
4019 * we don't need to allocate > 64K chunks for a full 16-bit table. | |
4020 */ | |
4021 void /* PRIVATE */ | |
4022 png_build_gamma_table(png_structp png_ptr) | |
4023 { | |
4024 png_debug(1, "in png_build_gamma_table\n"); | |
4025 | |
4026 if (png_ptr->bit_depth <= 8) | |
4027 { | |
4028 int i; | |
4029 double g; | |
4030 | |
4031 if (png_ptr->screen_gamma > .000001) | |
4032 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); | |
4033 else | |
4034 g = 1.0; | |
4035 | |
4036 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, | |
4037 (png_uint_32)256); | |
4038 | |
4039 for (i = 0; i < 256; i++) | |
4040 { | |
4041 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, | |
4042 g) * 255.0 + .5); | |
4043 } | |
4044 | |
4045 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ | |
4046 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
4047 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) | |
4048 { | |
4049 | |
4050 g = 1.0 / (png_ptr->gamma); | |
4051 | |
4052 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, | |
4053 (png_uint_32)256); | |
4054 | |
4055 for (i = 0; i < 256; i++) | |
4056 { | |
4057 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, | |
4058 g) * 255.0 + .5); | |
4059 } | |
4060 | |
4061 | |
4062 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, | |
4063 (png_uint_32)256); | |
4064 | |
4065 if(png_ptr->screen_gamma > 0.000001) | |
4066 g = 1.0 / png_ptr->screen_gamma; | |
4067 else | |
4068 g = png_ptr->gamma; /* probably doing rgb_to_gray */ | |
4069 | |
4070 for (i = 0; i < 256; i++) | |
4071 { | |
4072 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, | |
4073 g) * 255.0 + .5); | |
4074 | |
4075 } | |
4076 } | |
4077 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ | |
4078 } | |
4079 else | |
4080 { | |
4081 double g; | |
4082 int i, j, shift, num; | |
4083 int sig_bit; | |
4084 png_uint_32 ig; | |
4085 | |
4086 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) | |
4087 { | |
4088 sig_bit = (int)png_ptr->sig_bit.red; | |
4089 if ((int)png_ptr->sig_bit.green > sig_bit) | |
4090 sig_bit = png_ptr->sig_bit.green; | |
4091 if ((int)png_ptr->sig_bit.blue > sig_bit) | |
4092 sig_bit = png_ptr->sig_bit.blue; | |
4093 } | |
4094 else | |
4095 { | |
4096 sig_bit = (int)png_ptr->sig_bit.gray; | |
4097 } | |
4098 | |
4099 if (sig_bit > 0) | |
4100 shift = 16 - sig_bit; | |
4101 else | |
4102 shift = 0; | |
4103 | |
4104 if (png_ptr->transformations & PNG_16_TO_8) | |
4105 { | |
4106 if (shift < (16 - PNG_MAX_GAMMA_8)) | |
4107 shift = (16 - PNG_MAX_GAMMA_8); | |
4108 } | |
4109 | |
4110 if (shift > 8) | |
4111 shift = 8; | |
4112 if (shift < 0) | |
4113 shift = 0; | |
4114 | |
4115 png_ptr->gamma_shift = (png_byte)shift; | |
4116 | |
4117 num = (1 << (8 - shift)); | |
4118 | |
4119 if (png_ptr->screen_gamma > .000001) | |
4120 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); | |
4121 else | |
4122 g = 1.0; | |
4123 | |
4124 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, | |
4125 (png_uint_32)(num * png_sizeof (png_uint_16p))); | |
4126 | |
4127 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) | |
4128 { | |
4129 double fin, fout; | |
4130 png_uint_32 last, max; | |
4131 | |
4132 for (i = 0; i < num; i++) | |
4133 { | |
4134 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, | |
4135 (png_uint_32)(256 * png_sizeof (png_uint_16))); | |
4136 } | |
4137 | |
4138 g = 1.0 / g; | |
4139 last = 0; | |
4140 for (i = 0; i < 256; i++) | |
4141 { | |
4142 fout = ((double)i + 0.5) / 256.0; | |
4143 fin = pow(fout, g); | |
4144 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); | |
4145 while (last <= max) | |
4146 { | |
4147 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] | |
4148 [(int)(last >> (8 - shift))] = (png_uint_16)( | |
4149 (png_uint_16)i | ((png_uint_16)i << 8)); | |
4150 last++; | |
4151 } | |
4152 } | |
4153 while (last < ((png_uint_32)num << 8)) | |
4154 { | |
4155 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] | |
4156 [(int)(last >> (8 - shift))] = (png_uint_16)65535L; | |
4157 last++; | |
4158 } | |
4159 } | |
4160 else | |
4161 { | |
4162 for (i = 0; i < num; i++) | |
4163 { | |
4164 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, | |
4165 (png_uint_32)(256 * png_sizeof (png_uint_16))); | |
4166 | |
4167 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); | |
4168 for (j = 0; j < 256; j++) | |
4169 { | |
4170 png_ptr->gamma_16_table[i][j] = | |
4171 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / | |
4172 65535.0, g) * 65535.0 + .5); | |
4173 } | |
4174 } | |
4175 } | |
4176 | |
4177 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ | |
4178 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) | |
4179 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) | |
4180 { | |
4181 | |
4182 g = 1.0 / (png_ptr->gamma); | |
4183 | |
4184 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, | |
4185 (png_uint_32)(num * png_sizeof (png_uint_16p ))); | |
4186 | |
4187 for (i = 0; i < num; i++) | |
4188 { | |
4189 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, | |
4190 (png_uint_32)(256 * png_sizeof (png_uint_16))); | |
4191 | |
4192 ig = (((png_uint_32)i * | |
4193 (png_uint_32)png_gamma_shift[shift]) >> 4); | |
4194 for (j = 0; j < 256; j++) | |
4195 { | |
4196 png_ptr->gamma_16_to_1[i][j] = | |
4197 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / | |
4198 65535.0, g) * 65535.0 + .5); | |
4199 } | |
4200 } | |
4201 | |
4202 if(png_ptr->screen_gamma > 0.000001) | |
4203 g = 1.0 / png_ptr->screen_gamma; | |
4204 else | |
4205 g = png_ptr->gamma; /* probably doing rgb_to_gray */ | |
4206 | |
4207 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, | |
4208 (png_uint_32)(num * png_sizeof (png_uint_16p))); | |
4209 | |
4210 for (i = 0; i < num; i++) | |
4211 { | |
4212 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, | |
4213 (png_uint_32)(256 * png_sizeof (png_uint_16))); | |
4214 | |
4215 ig = (((png_uint_32)i * | |
4216 (png_uint_32)png_gamma_shift[shift]) >> 4); | |
4217 for (j = 0; j < 256; j++) | |
4218 { | |
4219 png_ptr->gamma_16_from_1[i][j] = | |
4220 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / | |
4221 65535.0, g) * 65535.0 + .5); | |
4222 } | |
4223 } | |
4224 } | |
4225 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ | |
4226 } | |
4227 } | |
4228 #endif | |
4229 /* To do: install integer version of png_build_gamma_table here */ | |
4230 #endif | |
4231 | |
4232 #if defined(PNG_MNG_FEATURES_SUPPORTED) | |
4233 /* undoes intrapixel differencing */ | |
4234 void /* PRIVATE */ | |
4235 png_do_read_intrapixel(png_row_infop row_info, png_bytep row) | |
4236 { | |
4237 png_debug(1, "in png_do_read_intrapixel\n"); | |
4238 if ( | |
4239 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
4240 row != NULL && row_info != NULL && | |
4241 #endif | |
4242 (row_info->color_type & PNG_COLOR_MASK_COLOR)) | |
4243 { | |
4244 int bytes_per_pixel; | |
4245 png_uint_32 row_width = row_info->width; | |
4246 if (row_info->bit_depth == 8) | |
4247 { | |
4248 png_bytep rp; | |
4249 png_uint_32 i; | |
4250 | |
4251 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
4252 bytes_per_pixel = 3; | |
4253 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
4254 bytes_per_pixel = 4; | |
4255 else | |
4256 return; | |
4257 | |
4258 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
4259 { | |
4260 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); | |
4261 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); | |
4262 } | |
4263 } | |
4264 else if (row_info->bit_depth == 16) | |
4265 { | |
4266 png_bytep rp; | |
4267 png_uint_32 i; | |
4268 | |
4269 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
4270 bytes_per_pixel = 6; | |
4271 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
4272 bytes_per_pixel = 8; | |
4273 else | |
4274 return; | |
4275 | |
4276 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
4277 { | |
4278 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); | |
4279 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); | |
4280 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); | |
4281 png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); | |
4282 png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); | |
4283 *(rp ) = (png_byte)((red >> 8) & 0xff); | |
4284 *(rp+1) = (png_byte)(red & 0xff); | |
4285 *(rp+4) = (png_byte)((blue >> 8) & 0xff); | |
4286 *(rp+5) = (png_byte)(blue & 0xff); | |
4287 } | |
4288 } | |
4289 } | |
4290 } | |
4291 #endif /* PNG_MNG_FEATURES_SUPPORTED */ | |
4292 #endif /* PNG_READ_SUPPORTED */ |