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