Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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