Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/libpng/pngrtran.c
Line
Count
Source (jump to first uncovered line)
1
2
/* pngrtran.c - transforms the data in a row for PNG readers
3
 *
4
 * Last changed in libpng 1.6.35 [July 15, 2018]
5
 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 *
13
 * This file contains functions optionally called by an application
14
 * in order to tell libpng how to handle data when reading a PNG.
15
 * Transformations that are used in both reading and writing are
16
 * in pngtrans.c.
17
 */
18
19
#include "pngpriv.h"
20
21
#ifdef PNG_READ_SUPPORTED
22
23
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
24
void PNGAPI
25
png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
26
0
{
27
0
   png_debug(1, "in png_set_crc_action");
28
0
29
0
   if (png_ptr == NULL)
30
0
      return;
31
0
32
0
   /* Tell libpng how we react to CRC errors in critical chunks */
33
0
   switch (crit_action)
34
0
   {
35
0
      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
36
0
         break;
37
0
38
0
      case PNG_CRC_WARN_USE:                               /* Warn/use data */
39
0
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
40
0
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
41
0
         break;
42
0
43
0
      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
44
0
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
45
0
         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
46
0
                           PNG_FLAG_CRC_CRITICAL_IGNORE;
47
0
         break;
48
0
49
0
      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
50
0
         png_warning(png_ptr,
51
0
             "Can't discard critical data on CRC error");
52
0
         /* FALLTHROUGH */
53
0
      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
54
0
55
0
      case PNG_CRC_DEFAULT:
56
0
      default:
57
0
         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
58
0
         break;
59
0
   }
60
0
61
0
   /* Tell libpng how we react to CRC errors in ancillary chunks */
62
0
   switch (ancil_action)
63
0
   {
64
0
      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
65
0
         break;
66
0
67
0
      case PNG_CRC_WARN_USE:                              /* Warn/use data */
68
0
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
69
0
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
70
0
         break;
71
0
72
0
      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
73
0
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
74
0
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
75
0
                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
76
0
         break;
77
0
78
0
      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
79
0
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
80
0
         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
81
0
         break;
82
0
83
0
      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
84
0
85
0
      case PNG_CRC_DEFAULT:
86
0
      default:
87
0
         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
88
0
         break;
89
0
   }
90
0
}
91
92
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
93
/* Is it OK to set a transformation now?  Only if png_start_read_image or
94
 * png_read_update_info have not been called.  It is not necessary for the IHDR
95
 * to have been read in all cases; the need_IHDR parameter allows for this
96
 * check too.
97
 */
98
static int
99
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
100
0
{
101
0
   if (png_ptr != NULL)
102
0
   {
103
0
      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
104
0
         png_app_error(png_ptr,
105
0
             "invalid after png_start_read_image or png_read_update_info");
106
0
107
0
      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
108
0
         png_app_error(png_ptr, "invalid before the PNG header has been read");
109
0
110
0
      else
111
0
      {
112
0
         /* Turn on failure to initialize correctly for all transforms. */
113
0
         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
114
0
115
0
         return 1; /* Ok */
116
0
      }
117
0
   }
118
0
119
0
   return 0; /* no png_error possible! */
120
0
}
121
#endif
122
123
#ifdef PNG_READ_BACKGROUND_SUPPORTED
124
/* Handle alpha and tRNS via a background color */
125
void PNGFAPI
126
png_set_background_fixed(png_structrp png_ptr,
127
    png_const_color_16p background_color, int background_gamma_code,
128
    int need_expand, png_fixed_point background_gamma)
129
{
130
   png_debug(1, "in png_set_background_fixed");
131
132
   if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
133
      return;
134
135
   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
136
   {
137
      png_warning(png_ptr, "Application must supply a known background gamma");
138
      return;
139
   }
140
141
   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
142
   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
143
   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
144
145
   png_ptr->background = *background_color;
146
   png_ptr->background_gamma = background_gamma;
147
   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
148
   if (need_expand != 0)
149
      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
150
   else
151
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
152
}
153
154
#  ifdef PNG_FLOATING_POINT_SUPPORTED
155
void PNGAPI
156
png_set_background(png_structrp png_ptr,
157
    png_const_color_16p background_color, int background_gamma_code,
158
    int need_expand, double background_gamma)
159
{
160
   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
161
      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
162
}
163
#  endif /* FLOATING_POINT */
164
#endif /* READ_BACKGROUND */
165
166
/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
167
 * one that pngrtran does first (scale) happens.  This is necessary to allow the
168
 * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
169
 */
170
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
171
void PNGAPI
172
png_set_scale_16(png_structrp png_ptr)
173
0
{
174
0
   png_debug(1, "in png_set_scale_16");
175
0
176
0
   if (png_rtran_ok(png_ptr, 0) == 0)
177
0
      return;
178
0
179
0
   png_ptr->transformations |= PNG_SCALE_16_TO_8;
180
0
}
181
#endif
182
183
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
184
/* Chop 16-bit depth files to 8-bit depth */
185
void PNGAPI
186
png_set_strip_16(png_structrp png_ptr)
187
{
188
   png_debug(1, "in png_set_strip_16");
189
190
   if (png_rtran_ok(png_ptr, 0) == 0)
191
      return;
192
193
   png_ptr->transformations |= PNG_16_TO_8;
194
}
195
#endif
196
197
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
198
void PNGAPI
199
png_set_strip_alpha(png_structrp png_ptr)
200
{
201
   png_debug(1, "in png_set_strip_alpha");
202
203
   if (png_rtran_ok(png_ptr, 0) == 0)
204
      return;
205
206
   png_ptr->transformations |= PNG_STRIP_ALPHA;
207
}
208
#endif
209
210
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
211
static png_fixed_point
212
translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
213
    int is_screen)
214
0
{
215
0
   /* Check for flag values.  The main reason for having the old Mac value as a
216
0
    * flag is that it is pretty near impossible to work out what the correct
217
0
    * value is from Apple documentation - a working Mac system is needed to
218
0
    * discover the value!
219
0
    */
220
0
   if (output_gamma == PNG_DEFAULT_sRGB ||
221
0
      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
222
0
   {
223
0
      /* If there is no sRGB support this just sets the gamma to the standard
224
0
       * sRGB value.  (This is a side effect of using this function!)
225
0
       */
226
0
#     ifdef PNG_READ_sRGB_SUPPORTED
227
0
         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
228
#     else
229
         PNG_UNUSED(png_ptr)
230
#     endif
231
0
      if (is_screen != 0)
232
0
         output_gamma = PNG_GAMMA_sRGB;
233
0
      else
234
0
         output_gamma = PNG_GAMMA_sRGB_INVERSE;
235
0
   }
236
0
237
0
   else if (output_gamma == PNG_GAMMA_MAC_18 ||
238
0
      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
239
0
   {
240
0
      if (is_screen != 0)
241
0
         output_gamma = PNG_GAMMA_MAC_OLD;
242
0
      else
243
0
         output_gamma = PNG_GAMMA_MAC_INVERSE;
244
0
   }
245
0
246
0
   return output_gamma;
247
0
}
248
249
#  ifdef PNG_FLOATING_POINT_SUPPORTED
250
static png_fixed_point
251
convert_gamma_value(png_structrp png_ptr, double output_gamma)
252
0
{
253
0
   /* The following silently ignores cases where fixed point (times 100,000)
254
0
    * gamma values are passed to the floating point API.  This is safe and it
255
0
    * means the fixed point constants work just fine with the floating point
256
0
    * API.  The alternative would just lead to undetected errors and spurious
257
0
    * bug reports.  Negative values fail inside the _fixed API unless they
258
0
    * correspond to the flag values.
259
0
    */
260
0
   if (output_gamma > 0 && output_gamma < 128)
261
0
      output_gamma *= PNG_FP_1;
262
0
263
0
   /* This preserves -1 and -2 exactly: */
264
0
   output_gamma = floor(output_gamma + .5);
265
0
266
0
   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
267
0
      png_fixed_error(png_ptr, "gamma value");
268
0
269
0
   return (png_fixed_point)output_gamma;
270
0
}
271
#  endif
272
#endif /* READ_ALPHA_MODE || READ_GAMMA */
273
274
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
275
void PNGFAPI
276
png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
277
    png_fixed_point output_gamma)
278
{
279
   int compose = 0;
280
   png_fixed_point file_gamma;
281
282
   png_debug(1, "in png_set_alpha_mode");
283
284
   if (png_rtran_ok(png_ptr, 0) == 0)
285
      return;
286
287
   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
288
289
   /* Validate the value to ensure it is in a reasonable range. The value
290
    * is expected to be 1 or greater, but this range test allows for some
291
    * viewing correction values.  The intent is to weed out users of this API
292
    * who use the inverse of the gamma value accidentally!  Since some of these
293
    * values are reasonable this may have to be changed:
294
    *
295
    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
296
    * gamma of 36, and its reciprocal.)
297
    */
298
   if (output_gamma < 1000 || output_gamma > 10000000)
299
      png_error(png_ptr, "output gamma out of expected range");
300
301
   /* The default file gamma is the inverse of the output gamma; the output
302
    * gamma may be changed below so get the file value first:
303
    */
304
   file_gamma = png_reciprocal(output_gamma);
305
306
   /* There are really 8 possibilities here, composed of any combination
307
    * of:
308
    *
309
    *    premultiply the color channels
310
    *    do not encode non-opaque pixels
311
    *    encode the alpha as well as the color channels
312
    *
313
    * The differences disappear if the input/output ('screen') gamma is 1.0,
314
    * because then the encoding is a no-op and there is only the choice of
315
    * premultiplying the color channels or not.
316
    *
317
    * png_set_alpha_mode and png_set_background interact because both use
318
    * png_compose to do the work.  Calling both is only useful when
319
    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
320
    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
321
    */
322
   switch (mode)
323
   {
324
      case PNG_ALPHA_PNG:        /* default: png standard */
325
         /* No compose, but it may be set by png_set_background! */
326
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
327
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
328
         break;
329
330
      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
331
         compose = 1;
332
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
333
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
334
         /* The output is linear: */
335
         output_gamma = PNG_FP_1;
336
         break;
337
338
      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
339
         compose = 1;
340
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
341
         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
342
         /* output_gamma records the encoding of opaque pixels! */
343
         break;
344
345
      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
346
         compose = 1;
347
         png_ptr->transformations |= PNG_ENCODE_ALPHA;
348
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
349
         break;
350
351
      default:
352
         png_error(png_ptr, "invalid alpha mode");
353
   }
354
355
   /* Only set the default gamma if the file gamma has not been set (this has
356
    * the side effect that the gamma in a second call to png_set_alpha_mode will
357
    * be ignored.)
358
    */
359
   if (png_ptr->colorspace.gamma == 0)
360
   {
361
      png_ptr->colorspace.gamma = file_gamma;
362
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
363
   }
364
365
   /* But always set the output gamma: */
366
   png_ptr->screen_gamma = output_gamma;
367
368
   /* Finally, if pre-multiplying, set the background fields to achieve the
369
    * desired result.
370
    */
371
   if (compose != 0)
372
   {
373
      /* And obtain alpha pre-multiplication by composing on black: */
374
      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
375
      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
376
      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
377
      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
378
379
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
380
         png_error(png_ptr,
381
             "conflicting calls to set alpha mode and background");
382
383
      png_ptr->transformations |= PNG_COMPOSE;
384
   }
385
}
386
387
#  ifdef PNG_FLOATING_POINT_SUPPORTED
388
void PNGAPI
389
png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
390
{
391
   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
392
       output_gamma));
393
}
394
#  endif
395
#endif
396
397
#ifdef PNG_READ_QUANTIZE_SUPPORTED
398
/* Dither file to 8-bit.  Supply a palette, the current number
399
 * of elements in the palette, the maximum number of elements
400
 * allowed, and a histogram if possible.  If the current number
401
 * of colors is greater than the maximum number, the palette will be
402
 * modified to fit in the maximum number.  "full_quantize" indicates
403
 * whether we need a quantizing cube set up for RGB images, or if we
404
 * simply are reducing the number of colors in a paletted image.
405
 */
406
407
typedef struct png_dsort_struct
408
{
409
   struct png_dsort_struct * next;
410
   png_byte left;
411
   png_byte right;
412
} png_dsort;
413
typedef png_dsort *   png_dsortp;
414
typedef png_dsort * * png_dsortpp;
415
416
void PNGAPI
417
png_set_quantize(png_structrp png_ptr, png_colorp palette,
418
    int num_palette, int maximum_colors, png_const_uint_16p histogram,
419
    int full_quantize)
420
{
421
   png_debug(1, "in png_set_quantize");
422
423
   if (png_rtran_ok(png_ptr, 0) == 0)
424
      return;
425
426
   png_ptr->transformations |= PNG_QUANTIZE;
427
428
   if (full_quantize == 0)
429
   {
430
      int i;
431
432
      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
433
          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
434
      for (i = 0; i < num_palette; i++)
435
         png_ptr->quantize_index[i] = (png_byte)i;
436
   }
437
438
   if (num_palette > maximum_colors)
439
   {
440
      if (histogram != NULL)
441
      {
442
         /* This is easy enough, just throw out the least used colors.
443
          * Perhaps not the best solution, but good enough.
444
          */
445
446
         int i;
447
448
         /* Initialize an array to sort colors */
449
         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
450
             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
451
452
         /* Initialize the quantize_sort array */
453
         for (i = 0; i < num_palette; i++)
454
            png_ptr->quantize_sort[i] = (png_byte)i;
455
456
         /* Find the least used palette entries by starting a
457
          * bubble sort, and running it until we have sorted
458
          * out enough colors.  Note that we don't care about
459
          * sorting all the colors, just finding which are
460
          * least used.
461
          */
462
463
         for (i = num_palette - 1; i >= maximum_colors; i--)
464
         {
465
            int done; /* To stop early if the list is pre-sorted */
466
            int j;
467
468
            done = 1;
469
            for (j = 0; j < i; j++)
470
            {
471
               if (histogram[png_ptr->quantize_sort[j]]
472
                   < histogram[png_ptr->quantize_sort[j + 1]])
473
               {
474
                  png_byte t;
475
476
                  t = png_ptr->quantize_sort[j];
477
                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
478
                  png_ptr->quantize_sort[j + 1] = t;
479
                  done = 0;
480
               }
481
            }
482
483
            if (done != 0)
484
               break;
485
         }
486
487
         /* Swap the palette around, and set up a table, if necessary */
488
         if (full_quantize != 0)
489
         {
490
            int j = num_palette;
491
492
            /* Put all the useful colors within the max, but don't
493
             * move the others.
494
             */
495
            for (i = 0; i < maximum_colors; i++)
496
            {
497
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
498
               {
499
                  do
500
                     j--;
501
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
502
503
                  palette[i] = palette[j];
504
               }
505
            }
506
         }
507
         else
508
         {
509
            int j = num_palette;
510
511
            /* Move all the used colors inside the max limit, and
512
             * develop a translation table.
513
             */
514
            for (i = 0; i < maximum_colors; i++)
515
            {
516
               /* Only move the colors we need to */
517
               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
518
               {
519
                  png_color tmp_color;
520
521
                  do
522
                     j--;
523
                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
524
525
                  tmp_color = palette[j];
526
                  palette[j] = palette[i];
527
                  palette[i] = tmp_color;
528
                  /* Indicate where the color went */
529
                  png_ptr->quantize_index[j] = (png_byte)i;
530
                  png_ptr->quantize_index[i] = (png_byte)j;
531
               }
532
            }
533
534
            /* Find closest color for those colors we are not using */
535
            for (i = 0; i < num_palette; i++)
536
            {
537
               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
538
               {
539
                  int min_d, k, min_k, d_index;
540
541
                  /* Find the closest color to one we threw out */
542
                  d_index = png_ptr->quantize_index[i];
543
                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
544
                  for (k = 1, min_k = 0; k < maximum_colors; k++)
545
                  {
546
                     int d;
547
548
                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
549
550
                     if (d < min_d)
551
                     {
552
                        min_d = d;
553
                        min_k = k;
554
                     }
555
                  }
556
                  /* Point to closest color */
557
                  png_ptr->quantize_index[i] = (png_byte)min_k;
558
               }
559
            }
560
         }
561
         png_free(png_ptr, png_ptr->quantize_sort);
562
         png_ptr->quantize_sort = NULL;
563
      }
564
      else
565
      {
566
         /* This is much harder to do simply (and quickly).  Perhaps
567
          * we need to go through a median cut routine, but those
568
          * don't always behave themselves with only a few colors
569
          * as input.  So we will just find the closest two colors,
570
          * and throw out one of them (chosen somewhat randomly).
571
          * [We don't understand this at all, so if someone wants to
572
          *  work on improving it, be our guest - AED, GRP]
573
          */
574
         int i;
575
         int max_d;
576
         int num_new_palette;
577
         png_dsortp t;
578
         png_dsortpp hash;
579
580
         t = NULL;
581
582
         /* Initialize palette index arrays */
583
         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
584
             (png_alloc_size_t)((png_uint_32)num_palette *
585
             (sizeof (png_byte))));
586
         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
587
             (png_alloc_size_t)((png_uint_32)num_palette *
588
             (sizeof (png_byte))));
589
590
         /* Initialize the sort array */
591
         for (i = 0; i < num_palette; i++)
592
         {
593
            png_ptr->index_to_palette[i] = (png_byte)i;
594
            png_ptr->palette_to_index[i] = (png_byte)i;
595
         }
596
597
         hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
598
             (sizeof (png_dsortp))));
599
600
         num_new_palette = num_palette;
601
602
         /* Initial wild guess at how far apart the farthest pixel
603
          * pair we will be eliminating will be.  Larger
604
          * numbers mean more areas will be allocated, Smaller
605
          * numbers run the risk of not saving enough data, and
606
          * having to do this all over again.
607
          *
608
          * I have not done extensive checking on this number.
609
          */
610
         max_d = 96;
611
612
         while (num_new_palette > maximum_colors)
613
         {
614
            for (i = 0; i < num_new_palette - 1; i++)
615
            {
616
               int j;
617
618
               for (j = i + 1; j < num_new_palette; j++)
619
               {
620
                  int d;
621
622
                  d = PNG_COLOR_DIST(palette[i], palette[j]);
623
624
                  if (d <= max_d)
625
                  {
626
627
                     t = (png_dsortp)png_malloc_warn(png_ptr,
628
                         (png_alloc_size_t)(sizeof (png_dsort)));
629
630
                     if (t == NULL)
631
                         break;
632
633
                     t->next = hash[d];
634
                     t->left = (png_byte)i;
635
                     t->right = (png_byte)j;
636
                     hash[d] = t;
637
                  }
638
               }
639
               if (t == NULL)
640
                  break;
641
            }
642
643
            if (t != NULL)
644
            for (i = 0; i <= max_d; i++)
645
            {
646
               if (hash[i] != NULL)
647
               {
648
                  png_dsortp p;
649
650
                  for (p = hash[i]; p; p = p->next)
651
                  {
652
                     if ((int)png_ptr->index_to_palette[p->left]
653
                         < num_new_palette &&
654
                         (int)png_ptr->index_to_palette[p->right]
655
                         < num_new_palette)
656
                     {
657
                        int j, next_j;
658
659
                        if (num_new_palette & 0x01)
660
                        {
661
                           j = p->left;
662
                           next_j = p->right;
663
                        }
664
                        else
665
                        {
666
                           j = p->right;
667
                           next_j = p->left;
668
                        }
669
670
                        num_new_palette--;
671
                        palette[png_ptr->index_to_palette[j]]
672
                            = palette[num_new_palette];
673
                        if (full_quantize == 0)
674
                        {
675
                           int k;
676
677
                           for (k = 0; k < num_palette; k++)
678
                           {
679
                              if (png_ptr->quantize_index[k] ==
680
                                  png_ptr->index_to_palette[j])
681
                                 png_ptr->quantize_index[k] =
682
                                     png_ptr->index_to_palette[next_j];
683
684
                              if ((int)png_ptr->quantize_index[k] ==
685
                                  num_new_palette)
686
                                 png_ptr->quantize_index[k] =
687
                                     png_ptr->index_to_palette[j];
688
                           }
689
                        }
690
691
                        png_ptr->index_to_palette[png_ptr->palette_to_index
692
                            [num_new_palette]] = png_ptr->index_to_palette[j];
693
694
                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
695
                            = png_ptr->palette_to_index[num_new_palette];
696
697
                        png_ptr->index_to_palette[j] =
698
                            (png_byte)num_new_palette;
699
700
                        png_ptr->palette_to_index[num_new_palette] =
701
                            (png_byte)j;
702
                     }
703
                     if (num_new_palette <= maximum_colors)
704
                        break;
705
                  }
706
                  if (num_new_palette <= maximum_colors)
707
                     break;
708
               }
709
            }
710
711
            for (i = 0; i < 769; i++)
712
            {
713
               if (hash[i] != NULL)
714
               {
715
                  png_dsortp p = hash[i];
716
                  while (p)
717
                  {
718
                     t = p->next;
719
                     png_free(png_ptr, p);
720
                     p = t;
721
                  }
722
               }
723
               hash[i] = 0;
724
            }
725
            max_d += 96;
726
         }
727
         png_free(png_ptr, hash);
728
         png_free(png_ptr, png_ptr->palette_to_index);
729
         png_free(png_ptr, png_ptr->index_to_palette);
730
         png_ptr->palette_to_index = NULL;
731
         png_ptr->index_to_palette = NULL;
732
      }
733
      num_palette = maximum_colors;
734
   }
735
   if (png_ptr->palette == NULL)
736
   {
737
      png_ptr->palette = palette;
738
   }
739
   png_ptr->num_palette = (png_uint_16)num_palette;
740
741
   if (full_quantize != 0)
742
   {
743
      int i;
744
      png_bytep distance;
745
      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
746
          PNG_QUANTIZE_BLUE_BITS;
747
      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
748
      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
749
      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
750
      size_t num_entries = ((size_t)1 << total_bits);
751
752
      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
753
          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
754
755
      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
756
          (sizeof (png_byte))));
757
758
      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
759
760
      for (i = 0; i < num_palette; i++)
761
      {
762
         int ir, ig, ib;
763
         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
764
         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
765
         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
766
767
         for (ir = 0; ir < num_red; ir++)
768
         {
769
            /* int dr = abs(ir - r); */
770
            int dr = ((ir > r) ? ir - r : r - ir);
771
            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
772
                PNG_QUANTIZE_GREEN_BITS));
773
774
            for (ig = 0; ig < num_green; ig++)
775
            {
776
               /* int dg = abs(ig - g); */
777
               int dg = ((ig > g) ? ig - g : g - ig);
778
               int dt = dr + dg;
779
               int dm = ((dr > dg) ? dr : dg);
780
               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
781
782
               for (ib = 0; ib < num_blue; ib++)
783
               {
784
                  int d_index = index_g | ib;
785
                  /* int db = abs(ib - b); */
786
                  int db = ((ib > b) ? ib - b : b - ib);
787
                  int dmax = ((dm > db) ? dm : db);
788
                  int d = dmax + dt + db;
789
790
                  if (d < (int)distance[d_index])
791
                  {
792
                     distance[d_index] = (png_byte)d;
793
                     png_ptr->palette_lookup[d_index] = (png_byte)i;
794
                  }
795
               }
796
            }
797
         }
798
      }
799
800
      png_free(png_ptr, distance);
801
   }
802
}
803
#endif /* READ_QUANTIZE */
804
805
#ifdef PNG_READ_GAMMA_SUPPORTED
806
void PNGFAPI
807
png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
808
    png_fixed_point file_gamma)
809
0
{
810
0
   png_debug(1, "in png_set_gamma_fixed");
811
0
812
0
   if (png_rtran_ok(png_ptr, 0) == 0)
813
0
      return;
814
0
815
0
   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
816
0
   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
817
0
   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
818
0
819
0
   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
820
0
    * premultiplied alpha support; this actually hides an undocumented feature
821
0
    * of the previous implementation which allowed gamma processing to be
822
0
    * disabled in background handling.  There is no evidence (so far) that this
823
0
    * was being used; however, png_set_background itself accepted and must still
824
0
    * accept '0' for the gamma value it takes, because it isn't always used.
825
0
    *
826
0
    * Since this is an API change (albeit a very minor one that removes an
827
0
    * undocumented API feature) the following checks were only enabled in
828
0
    * libpng-1.6.0.
829
0
    */
830
0
   if (file_gamma <= 0)
831
0
      png_error(png_ptr, "invalid file gamma in png_set_gamma");
832
0
833
0
   if (scrn_gamma <= 0)
834
0
      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
835
0
836
0
   /* Set the gamma values unconditionally - this overrides the value in the PNG
837
0
    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
838
0
    * different, easier, way to default the file gamma.
839
0
    */
840
0
   png_ptr->colorspace.gamma = file_gamma;
841
0
   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
842
0
   png_ptr->screen_gamma = scrn_gamma;
843
0
}
844
845
#  ifdef PNG_FLOATING_POINT_SUPPORTED
846
void PNGAPI
847
png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
848
0
{
849
0
   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
850
0
       convert_gamma_value(png_ptr, file_gamma));
851
0
}
852
#  endif /* FLOATING_POINT */
853
#endif /* READ_GAMMA */
854
855
#ifdef PNG_READ_EXPAND_SUPPORTED
856
/* Expand paletted images to RGB, expand grayscale images of
857
 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
858
 * to alpha channels.
859
 */
860
void PNGAPI
861
png_set_expand(png_structrp png_ptr)
862
0
{
863
0
   png_debug(1, "in png_set_expand");
864
0
865
0
   if (png_rtran_ok(png_ptr, 0) == 0)
866
0
      return;
867
0
868
0
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
869
0
}
870
871
/* GRR 19990627:  the following three functions currently are identical
872
 *  to png_set_expand().  However, it is entirely reasonable that someone
873
 *  might wish to expand an indexed image to RGB but *not* expand a single,
874
 *  fully transparent palette entry to a full alpha channel--perhaps instead
875
 *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
876
 *  the transparent color with a particular RGB value, or drop tRNS entirely.
877
 *  IOW, a future version of the library may make the transformations flag
878
 *  a bit more fine-grained, with separate bits for each of these three
879
 *  functions.
880
 *
881
 *  More to the point, these functions make it obvious what libpng will be
882
 *  doing, whereas "expand" can (and does) mean any number of things.
883
 *
884
 *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
885
 *  to expand only the sample depth but not to expand the tRNS to alpha
886
 *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
887
 */
888
889
/* Expand paletted images to RGB. */
890
void PNGAPI
891
png_set_palette_to_rgb(png_structrp png_ptr)
892
0
{
893
0
   png_debug(1, "in png_set_palette_to_rgb");
894
0
895
0
   if (png_rtran_ok(png_ptr, 0) == 0)
896
0
      return;
897
0
898
0
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
899
0
}
900
901
/* Expand grayscale images of less than 8-bit depth to 8 bits. */
902
void PNGAPI
903
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
904
0
{
905
0
   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
906
0
907
0
   if (png_rtran_ok(png_ptr, 0) == 0)
908
0
      return;
909
0
910
0
   png_ptr->transformations |= PNG_EXPAND;
911
0
}
912
913
/* Expand tRNS chunks to alpha channels. */
914
void PNGAPI
915
png_set_tRNS_to_alpha(png_structrp png_ptr)
916
0
{
917
0
   png_debug(1, "in png_set_tRNS_to_alpha");
918
0
919
0
   if (png_rtran_ok(png_ptr, 0) == 0)
920
0
      return;
921
0
922
0
   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
923
0
}
924
#endif /* READ_EXPAND */
925
926
#ifdef PNG_READ_EXPAND_16_SUPPORTED
927
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
928
 * it may not work correctly.)
929
 */
930
void PNGAPI
931
png_set_expand_16(png_structrp png_ptr)
932
{
933
   png_debug(1, "in png_set_expand_16");
934
935
   if (png_rtran_ok(png_ptr, 0) == 0)
936
      return;
937
938
   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
939
}
940
#endif
941
942
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
943
void PNGAPI
944
png_set_gray_to_rgb(png_structrp png_ptr)
945
0
{
946
0
   png_debug(1, "in png_set_gray_to_rgb");
947
0
948
0
   if (png_rtran_ok(png_ptr, 0) == 0)
949
0
      return;
950
0
951
0
   /* Because rgb must be 8 bits or more: */
952
0
   png_set_expand_gray_1_2_4_to_8(png_ptr);
953
0
   png_ptr->transformations |= PNG_GRAY_TO_RGB;
954
0
}
955
#endif
956
957
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
958
void PNGFAPI
959
png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
960
    png_fixed_point red, png_fixed_point green)
961
{
962
   png_debug(1, "in png_set_rgb_to_gray");
963
964
   /* Need the IHDR here because of the check on color_type below. */
965
   /* TODO: fix this */
966
   if (png_rtran_ok(png_ptr, 1) == 0)
967
      return;
968
969
   switch (error_action)
970
   {
971
      case PNG_ERROR_ACTION_NONE:
972
         png_ptr->transformations |= PNG_RGB_TO_GRAY;
973
         break;
974
975
      case PNG_ERROR_ACTION_WARN:
976
         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
977
         break;
978
979
      case PNG_ERROR_ACTION_ERROR:
980
         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
981
         break;
982
983
      default:
984
         png_error(png_ptr, "invalid error action to rgb_to_gray");
985
   }
986
987
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
988
#ifdef PNG_READ_EXPAND_SUPPORTED
989
      png_ptr->transformations |= PNG_EXPAND;
990
#else
991
   {
992
      /* Make this an error in 1.6 because otherwise the application may assume
993
       * that it just worked and get a memory overwrite.
994
       */
995
      png_error(png_ptr,
996
          "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
997
998
      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
999
   }
1000
#endif
1001
   {
1002
      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
1003
      {
1004
         png_uint_16 red_int, green_int;
1005
1006
         /* NOTE: this calculation does not round, but this behavior is retained
1007
          * for consistency; the inaccuracy is very small.  The code here always
1008
          * overwrites the coefficients, regardless of whether they have been
1009
          * defaulted or set already.
1010
          */
1011
         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
1012
         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1013
1014
         png_ptr->rgb_to_gray_red_coeff   = red_int;
1015
         png_ptr->rgb_to_gray_green_coeff = green_int;
1016
         png_ptr->rgb_to_gray_coefficients_set = 1;
1017
      }
1018
1019
      else
1020
      {
1021
         if (red >= 0 && green >= 0)
1022
            png_app_warning(png_ptr,
1023
                "ignoring out of range rgb_to_gray coefficients");
1024
1025
         /* Use the defaults, from the cHRM chunk if set, else the historical
1026
          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
1027
          * png_do_rgb_to_gray for more discussion of the values.  In this case
1028
          * the coefficients are not marked as 'set' and are not overwritten if
1029
          * something has already provided a default.
1030
          */
1031
         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1032
             png_ptr->rgb_to_gray_green_coeff == 0)
1033
         {
1034
            png_ptr->rgb_to_gray_red_coeff   = 6968;
1035
            png_ptr->rgb_to_gray_green_coeff = 23434;
1036
            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
1037
         }
1038
      }
1039
   }
1040
}
1041
1042
#ifdef PNG_FLOATING_POINT_SUPPORTED
1043
/* Convert a RGB image to a grayscale of the same width.  This allows us,
1044
 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
1045
 */
1046
1047
void PNGAPI
1048
png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
1049
    double green)
1050
{
1051
   png_set_rgb_to_gray_fixed(png_ptr, error_action,
1052
       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
1053
      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1054
}
1055
#endif /* FLOATING POINT */
1056
1057
#endif /* RGB_TO_GRAY */
1058
1059
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1060
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1061
void PNGAPI
1062
png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1063
    read_user_transform_fn)
1064
{
1065
   png_debug(1, "in png_set_read_user_transform_fn");
1066
1067
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1068
   png_ptr->transformations |= PNG_USER_TRANSFORM;
1069
   png_ptr->read_user_transform_fn = read_user_transform_fn;
1070
#endif
1071
}
1072
#endif
1073
1074
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1075
#ifdef PNG_READ_GAMMA_SUPPORTED
1076
/* In the case of gamma transformations only do transformations on images where
1077
 * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
1078
 * slows things down slightly, and also needlessly introduces small errors.
1079
 */
1080
static int /* PRIVATE */
1081
png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
1082
0
{
1083
0
   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
1084
0
    * correction as a difference of the overall transform from 1.0
1085
0
    *
1086
0
    * We want to compare the threshold with s*f - 1, if we get
1087
0
    * overflow here it is because of wacky gamma values so we
1088
0
    * turn on processing anyway.
1089
0
    */
1090
0
   png_fixed_point gtest;
1091
0
   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
1092
0
       png_gamma_significant(gtest);
1093
0
}
1094
#endif
1095
1096
/* Initialize everything needed for the read.  This includes modifying
1097
 * the palette.
1098
 */
1099
1100
/* For the moment 'png_init_palette_transformations' and
1101
 * 'png_init_rgb_transformations' only do some flag canceling optimizations.
1102
 * The intent is that these two routines should have palette or rgb operations
1103
 * extracted from 'png_init_read_transformations'.
1104
 */
1105
static void /* PRIVATE */
1106
png_init_palette_transformations(png_structrp png_ptr)
1107
0
{
1108
0
   /* Called to handle the (input) palette case.  In png_do_read_transformations
1109
0
    * the first step is to expand the palette if requested, so this code must
1110
0
    * take care to only make changes that are invariant with respect to the
1111
0
    * palette expansion, or only do them if there is no expansion.
1112
0
    *
1113
0
    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
1114
0
    * to 0.)
1115
0
    */
1116
0
   int input_has_alpha = 0;
1117
0
   int input_has_transparency = 0;
1118
0
1119
0
   if (png_ptr->num_trans > 0)
1120
0
   {
1121
0
      int i;
1122
0
1123
0
      /* Ignore if all the entries are opaque (unlikely!) */
1124
0
      for (i=0; i<png_ptr->num_trans; ++i)
1125
0
      {
1126
0
         if (png_ptr->trans_alpha[i] == 255)
1127
0
            continue;
1128
0
         else if (png_ptr->trans_alpha[i] == 0)
1129
0
            input_has_transparency = 1;
1130
0
         else
1131
0
         {
1132
0
            input_has_transparency = 1;
1133
0
            input_has_alpha = 1;
1134
0
            break;
1135
0
         }
1136
0
      }
1137
0
   }
1138
0
1139
0
   /* If no alpha we can optimize. */
1140
0
   if (input_has_alpha == 0)
1141
0
   {
1142
0
      /* Any alpha means background and associative alpha processing is
1143
0
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1144
0
       * and ENCODE_ALPHA are irrelevant.
1145
0
       */
1146
0
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1147
0
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1148
0
1149
0
      if (input_has_transparency == 0)
1150
0
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1151
0
   }
1152
0
1153
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1154
   /* png_set_background handling - deals with the complexity of whether the
1155
    * background color is in the file format or the screen format in the case
1156
    * where an 'expand' will happen.
1157
    */
1158
1159
   /* The following code cannot be entered in the alpha pre-multiplication case
1160
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1161
    */
1162
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
1163
       (png_ptr->transformations & PNG_EXPAND) != 0)
1164
   {
1165
      {
1166
         png_ptr->background.red   =
1167
             png_ptr->palette[png_ptr->background.index].red;
1168
         png_ptr->background.green =
1169
             png_ptr->palette[png_ptr->background.index].green;
1170
         png_ptr->background.blue  =
1171
             png_ptr->palette[png_ptr->background.index].blue;
1172
1173
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1174
        if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1175
        {
1176
           if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1177
           {
1178
              /* Invert the alpha channel (in tRNS) unless the pixels are
1179
               * going to be expanded, in which case leave it for later
1180
               */
1181
              int i, istop = png_ptr->num_trans;
1182
1183
              for (i=0; i<istop; i++)
1184
                 png_ptr->trans_alpha[i] = (png_byte)(255 -
1185
                    png_ptr->trans_alpha[i]);
1186
           }
1187
        }
1188
#endif /* READ_INVERT_ALPHA */
1189
      }
1190
   } /* background expand and (therefore) no alpha association. */
1191
#endif /* READ_EXPAND && READ_BACKGROUND */
1192
}
1193
1194
static void /* PRIVATE */
1195
png_init_rgb_transformations(png_structrp png_ptr)
1196
0
{
1197
0
   /* Added to libpng-1.5.4: check the color type to determine whether there
1198
0
    * is any alpha or transparency in the image and simply cancel the
1199
0
    * background and alpha mode stuff if there isn't.
1200
0
    */
1201
0
   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1202
0
   int input_has_transparency = png_ptr->num_trans > 0;
1203
0
1204
0
   /* If no alpha we can optimize. */
1205
0
   if (input_has_alpha == 0)
1206
0
   {
1207
0
      /* Any alpha means background and associative alpha processing is
1208
0
       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1209
0
       * and ENCODE_ALPHA are irrelevant.
1210
0
       */
1211
#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1212
         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1213
         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1214
#     endif
1215
1216
0
      if (input_has_transparency == 0)
1217
0
         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1218
0
   }
1219
0
1220
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1221
   /* png_set_background handling - deals with the complexity of whether the
1222
    * background color is in the file format or the screen format in the case
1223
    * where an 'expand' will happen.
1224
    */
1225
1226
   /* The following code cannot be entered in the alpha pre-multiplication case
1227
    * because PNG_BACKGROUND_EXPAND is cancelled below.
1228
    */
1229
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
1230
       (png_ptr->transformations & PNG_EXPAND) != 0 &&
1231
       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1232
       /* i.e., GRAY or GRAY_ALPHA */
1233
   {
1234
      {
1235
         /* Expand background and tRNS chunks */
1236
         int gray = png_ptr->background.gray;
1237
         int trans_gray = png_ptr->trans_color.gray;
1238
1239
         switch (png_ptr->bit_depth)
1240
         {
1241
            case 1:
1242
               gray *= 0xff;
1243
               trans_gray *= 0xff;
1244
               break;
1245
1246
            case 2:
1247
               gray *= 0x55;
1248
               trans_gray *= 0x55;
1249
               break;
1250
1251
            case 4:
1252
               gray *= 0x11;
1253
               trans_gray *= 0x11;
1254
               break;
1255
1256
            default:
1257
1258
            case 8:
1259
               /* FALLTHROUGH */ /*  (Already 8 bits) */
1260
1261
            case 16:
1262
               /* Already a full 16 bits */
1263
               break;
1264
         }
1265
1266
         png_ptr->background.red = png_ptr->background.green =
1267
            png_ptr->background.blue = (png_uint_16)gray;
1268
1269
         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1270
         {
1271
            png_ptr->trans_color.red = png_ptr->trans_color.green =
1272
               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
1273
         }
1274
      }
1275
   } /* background expand and (therefore) no alpha association. */
1276
#endif /* READ_EXPAND && READ_BACKGROUND */
1277
}
1278
1279
void /* PRIVATE */
1280
png_init_read_transformations(png_structrp png_ptr)
1281
0
{
1282
0
   png_debug(1, "in png_init_read_transformations");
1283
0
1284
0
   /* This internal function is called from png_read_start_row in pngrutil.c
1285
0
    * and it is called before the 'rowbytes' calculation is done, so the code
1286
0
    * in here can change or update the transformations flags.
1287
0
    *
1288
0
    * First do updates that do not depend on the details of the PNG image data
1289
0
    * being processed.
1290
0
    */
1291
0
1292
0
#ifdef PNG_READ_GAMMA_SUPPORTED
1293
0
   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1294
0
    * png_set_alpha_mode and this is another source for a default file gamma so
1295
0
    * the test needs to be performed later - here.  In addition prior to 1.5.4
1296
0
    * the tests were repeated for the PALETTE color type here - this is no
1297
0
    * longer necessary (and doesn't seem to have been necessary before.)
1298
0
    */
1299
0
   {
1300
0
      /* The following temporary indicates if overall gamma correction is
1301
0
       * required.
1302
0
       */
1303
0
      int gamma_correction = 0;
1304
0
1305
0
      if (png_ptr->colorspace.gamma != 0) /* has been set */
1306
0
      {
1307
0
         if (png_ptr->screen_gamma != 0) /* screen set too */
1308
0
            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1309
0
                png_ptr->screen_gamma);
1310
0
1311
0
         else
1312
0
            /* Assume the output matches the input; a long time default behavior
1313
0
             * of libpng, although the standard has nothing to say about this.
1314
0
             */
1315
0
            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
1316
0
      }
1317
0
1318
0
      else if (png_ptr->screen_gamma != 0)
1319
0
         /* The converse - assume the file matches the screen, note that this
1320
0
          * perhaps undesirable default can (from 1.5.4) be changed by calling
1321
0
          * png_set_alpha_mode (even if the alpha handling mode isn't required
1322
0
          * or isn't changed from the default.)
1323
0
          */
1324
0
         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1325
0
1326
0
      else /* neither are set */
1327
0
         /* Just in case the following prevents any processing - file and screen
1328
0
          * are both assumed to be linear and there is no way to introduce a
1329
0
          * third gamma value other than png_set_background with 'UNIQUE', and,
1330
0
          * prior to 1.5.4
1331
0
          */
1332
0
         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
1333
0
1334
0
      /* We have a gamma value now. */
1335
0
      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1336
0
1337
0
      /* Now turn the gamma transformation on or off as appropriate.  Notice
1338
0
       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
1339
0
       * composition may independently cause gamma correction because it needs
1340
0
       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
1341
0
       * hasn't been specified.)  In any case this flag may get turned off in
1342
0
       * the code immediately below if the transform can be handled outside the
1343
0
       * row loop.
1344
0
       */
1345
0
      if (gamma_correction != 0)
1346
0
         png_ptr->transformations |= PNG_GAMMA;
1347
0
1348
0
      else
1349
0
         png_ptr->transformations &= ~PNG_GAMMA;
1350
0
   }
1351
0
#endif
1352
0
1353
0
   /* Certain transformations have the effect of preventing other
1354
0
    * transformations that happen afterward in png_do_read_transformations;
1355
0
    * resolve the interdependencies here.  From the code of
1356
0
    * png_do_read_transformations the order is:
1357
0
    *
1358
0
    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
1359
0
    *  2) PNG_STRIP_ALPHA (if no compose)
1360
0
    *  3) PNG_RGB_TO_GRAY
1361
0
    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
1362
0
    *  5) PNG_COMPOSE
1363
0
    *  6) PNG_GAMMA
1364
0
    *  7) PNG_STRIP_ALPHA (if compose)
1365
0
    *  8) PNG_ENCODE_ALPHA
1366
0
    *  9) PNG_SCALE_16_TO_8
1367
0
    * 10) PNG_16_TO_8
1368
0
    * 11) PNG_QUANTIZE (converts to palette)
1369
0
    * 12) PNG_EXPAND_16
1370
0
    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
1371
0
    * 14) PNG_INVERT_MONO
1372
0
    * 15) PNG_INVERT_ALPHA
1373
0
    * 16) PNG_SHIFT
1374
0
    * 17) PNG_PACK
1375
0
    * 18) PNG_BGR
1376
0
    * 19) PNG_PACKSWAP
1377
0
    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1378
0
    * 21) PNG_SWAP_ALPHA
1379
0
    * 22) PNG_SWAP_BYTES
1380
0
    * 23) PNG_USER_TRANSFORM [must be last]
1381
0
    */
1382
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1383
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
1384
       (png_ptr->transformations & PNG_COMPOSE) == 0)
1385
   {
1386
      /* Stripping the alpha channel happens immediately after the 'expand'
1387
       * transformations, before all other transformation, so it cancels out
1388
       * the alpha handling.  It has the side effect negating the effect of
1389
       * PNG_EXPAND_tRNS too:
1390
       */
1391
      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
1392
         PNG_EXPAND_tRNS);
1393
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1394
1395
      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
1396
       * so transparency information would remain just so long as it wasn't
1397
       * expanded.  This produces unexpected API changes if the set of things
1398
       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
1399
       * documentation - which says ask for what you want, accept what you
1400
       * get.)  This makes the behavior consistent from 1.5.4:
1401
       */
1402
      png_ptr->num_trans = 0;
1403
   }
1404
#endif /* STRIP_ALPHA supported, no COMPOSE */
1405
1406
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1407
   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
1408
    * settings will have no effect.
1409
    */
1410
   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1411
   {
1412
      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1413
      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1414
   }
1415
#endif
1416
1417
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1418
   /* Make sure the coefficients for the rgb to gray conversion are set
1419
    * appropriately.
1420
    */
1421
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1422
      png_colorspace_set_rgb_coefficients(png_ptr);
1423
#endif
1424
1425
0
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1426
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1427
   /* Detect gray background and attempt to enable optimization for
1428
    * gray --> RGB case.
1429
    *
1430
    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
1431
    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
1432
    * background color might actually be gray yet not be flagged as such.
1433
    * This is not a problem for the current code, which uses
1434
    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
1435
    * png_do_gray_to_rgb() transformation.
1436
    *
1437
    * TODO: this code needs to be revised to avoid the complexity and
1438
    * interdependencies.  The color type of the background should be recorded in
1439
    * png_set_background, along with the bit depth, then the code has a record
1440
    * of exactly what color space the background is currently in.
1441
    */
1442
   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1443
   {
1444
      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1445
       * the file was grayscale the background value is gray.
1446
       */
1447
      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1448
         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1449
   }
1450
1451
   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1452
   {
1453
      /* PNG_COMPOSE: png_set_background was called with need_expand false,
1454
       * so the color is in the color space of the output or png_set_alpha_mode
1455
       * was called and the color is black.  Ignore RGB_TO_GRAY because that
1456
       * happens before GRAY_TO_RGB.
1457
       */
1458
      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1459
      {
1460
         if (png_ptr->background.red == png_ptr->background.green &&
1461
             png_ptr->background.red == png_ptr->background.blue)
1462
         {
1463
            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1464
            png_ptr->background.gray = png_ptr->background.red;
1465
         }
1466
      }
1467
   }
1468
#endif /* READ_EXPAND && READ_BACKGROUND */
1469
#endif /* READ_GRAY_TO_RGB */
1470
0
1471
0
   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
1472
0
    * can be performed directly on the palette, and some (such as rgb to gray)
1473
0
    * can be optimized inside the palette.  This is particularly true of the
1474
0
    * composite (background and alpha) stuff, which can be pretty much all done
1475
0
    * in the palette even if the result is expanded to RGB or gray afterward.
1476
0
    *
1477
0
    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
1478
0
    * earlier and the palette stuff is actually handled on the first row.  This
1479
0
    * leads to the reported bug that the palette returned by png_get_PLTE is not
1480
0
    * updated.
1481
0
    */
1482
0
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1483
0
      png_init_palette_transformations(png_ptr);
1484
0
1485
0
   else
1486
0
      png_init_rgb_transformations(png_ptr);
1487
0
1488
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1489
   defined(PNG_READ_EXPAND_16_SUPPORTED)
1490
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
1491
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
1492
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
1493
       png_ptr->bit_depth != 16)
1494
   {
1495
      /* TODO: fix this.  Because the expand_16 operation is after the compose
1496
       * handling the background color must be 8, not 16, bits deep, but the
1497
       * application will supply a 16-bit value so reduce it here.
1498
       *
1499
       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
1500
       * present, so that case is ok (until do_expand_16 is moved.)
1501
       *
1502
       * NOTE: this discards the low 16 bits of the user supplied background
1503
       * color, but until expand_16 works properly there is no choice!
1504
       */
1505
#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1506
      CHOP(png_ptr->background.red);
1507
      CHOP(png_ptr->background.green);
1508
      CHOP(png_ptr->background.blue);
1509
      CHOP(png_ptr->background.gray);
1510
#     undef CHOP
1511
   }
1512
#endif /* READ_BACKGROUND && READ_EXPAND_16 */
1513
1514
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1515
   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
1516
   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1517
   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
1518
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
1519
       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
1520
       png_ptr->bit_depth == 16)
1521
   {
1522
      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
1523
       * component this will also happen after PNG_COMPOSE and so the background
1524
       * color must be pre-expanded here.
1525
       *
1526
       * TODO: fix this too.
1527
       */
1528
      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
1529
      png_ptr->background.green =
1530
         (png_uint_16)(png_ptr->background.green * 257);
1531
      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
1532
      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
1533
   }
1534
#endif
1535
1536
0
   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
1537
0
    * background support (see the comments in scripts/pnglibconf.dfa), this
1538
0
    * allows pre-multiplication of the alpha channel to be implemented as
1539
0
    * compositing on black.  This is probably sub-optimal and has been done in
1540
0
    * 1.5.4 betas simply to enable external critique and testing (i.e. to
1541
0
    * implement the new API quickly, without lots of internal changes.)
1542
0
    */
1543
0
1544
0
#ifdef PNG_READ_GAMMA_SUPPORTED
1545
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1546
      /* Includes ALPHA_MODE */
1547
      png_ptr->background_1 = png_ptr->background;
1548
#  endif
1549
1550
0
   /* This needs to change - in the palette image case a whole set of tables are
1551
0
    * built when it would be quicker to just calculate the correct value for
1552
0
    * each palette entry directly.  Also, the test is too tricky - why check
1553
0
    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
1554
0
    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
1555
0
    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
1556
0
    * the gamma tables will not be built even if composition is required on a
1557
0
    * gamma encoded value.
1558
0
    *
1559
0
    * In 1.5.4 this is addressed below by an additional check on the individual
1560
0
    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
1561
0
    * tables.
1562
0
    */
1563
0
   if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
1564
0
       ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
1565
0
        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
1566
0
         png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
1567
0
        ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1568
0
         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
1569
0
          png_gamma_significant(png_ptr->screen_gamma) != 0
1570
#  ifdef PNG_READ_BACKGROUND_SUPPORTED
1571
         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
1572
           png_gamma_significant(png_ptr->background_gamma) != 0)
1573
#  endif
1574
0
        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
1575
0
       png_gamma_significant(png_ptr->screen_gamma) != 0))
1576
0
   {
1577
0
      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1578
0
1579
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1580
      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1581
      {
1582
         /* Issue a warning about this combination: because RGB_TO_GRAY is
1583
          * optimized to do the gamma transform if present yet do_background has
1584
          * to do the same thing if both options are set a
1585
          * double-gamma-correction happens.  This is true in all versions of
1586
          * libpng to date.
1587
          */
1588
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1589
            png_warning(png_ptr,
1590
                "libpng does not support gamma+background+rgb_to_gray");
1591
1592
         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
1593
         {
1594
            /* We don't get to here unless there is a tRNS chunk with non-opaque
1595
             * entries - see the checking code at the start of this function.
1596
             */
1597
            png_color back, back_1;
1598
            png_colorp palette = png_ptr->palette;
1599
            int num_palette = png_ptr->num_palette;
1600
            int i;
1601
            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1602
            {
1603
1604
               back.red = png_ptr->gamma_table[png_ptr->background.red];
1605
               back.green = png_ptr->gamma_table[png_ptr->background.green];
1606
               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
1607
1608
               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1609
               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1610
               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
1611
            }
1612
            else
1613
            {
1614
               png_fixed_point g, gs;
1615
1616
               switch (png_ptr->background_gamma_type)
1617
               {
1618
                  case PNG_BACKGROUND_GAMMA_SCREEN:
1619
                     g = (png_ptr->screen_gamma);
1620
                     gs = PNG_FP_1;
1621
                     break;
1622
1623
                  case PNG_BACKGROUND_GAMMA_FILE:
1624
                     g = png_reciprocal(png_ptr->colorspace.gamma);
1625
                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
1626
                         png_ptr->screen_gamma);
1627
                     break;
1628
1629
                  case PNG_BACKGROUND_GAMMA_UNIQUE:
1630
                     g = png_reciprocal(png_ptr->background_gamma);
1631
                     gs = png_reciprocal2(png_ptr->background_gamma,
1632
                         png_ptr->screen_gamma);
1633
                     break;
1634
                  default:
1635
                     g = PNG_FP_1;    /* back_1 */
1636
                     gs = PNG_FP_1;   /* back */
1637
                     break;
1638
               }
1639
1640
               if (png_gamma_significant(gs) != 0)
1641
               {
1642
                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
1643
                      gs);
1644
                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
1645
                      gs);
1646
                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1647
                      gs);
1648
               }
1649
1650
               else
1651
               {
1652
                  back.red   = (png_byte)png_ptr->background.red;
1653
                  back.green = (png_byte)png_ptr->background.green;
1654
                  back.blue  = (png_byte)png_ptr->background.blue;
1655
               }
1656
1657
               if (png_gamma_significant(g) != 0)
1658
               {
1659
                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
1660
                      g);
1661
                  back_1.green = png_gamma_8bit_correct(
1662
                      png_ptr->background.green, g);
1663
                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1664
                      g);
1665
               }
1666
1667
               else
1668
               {
1669
                  back_1.red   = (png_byte)png_ptr->background.red;
1670
                  back_1.green = (png_byte)png_ptr->background.green;
1671
                  back_1.blue  = (png_byte)png_ptr->background.blue;
1672
               }
1673
            }
1674
1675
            for (i = 0; i < num_palette; i++)
1676
            {
1677
               if (i < (int)png_ptr->num_trans &&
1678
                   png_ptr->trans_alpha[i] != 0xff)
1679
               {
1680
                  if (png_ptr->trans_alpha[i] == 0)
1681
                  {
1682
                     palette[i] = back;
1683
                  }
1684
                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
1685
                  {
1686
                     png_byte v, w;
1687
1688
                     v = png_ptr->gamma_to_1[palette[i].red];
1689
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
1690
                     palette[i].red = png_ptr->gamma_from_1[w];
1691
1692
                     v = png_ptr->gamma_to_1[palette[i].green];
1693
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
1694
                     palette[i].green = png_ptr->gamma_from_1[w];
1695
1696
                     v = png_ptr->gamma_to_1[palette[i].blue];
1697
                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
1698
                     palette[i].blue = png_ptr->gamma_from_1[w];
1699
                  }
1700
               }
1701
               else
1702
               {
1703
                  palette[i].red = png_ptr->gamma_table[palette[i].red];
1704
                  palette[i].green = png_ptr->gamma_table[palette[i].green];
1705
                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1706
               }
1707
            }
1708
1709
            /* Prevent the transformations being done again.
1710
             *
1711
             * NOTE: this is highly dubious; it removes the transformations in
1712
             * place.  This seems inconsistent with the general treatment of the
1713
             * transformations elsewhere.
1714
             */
1715
            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
1716
         } /* color_type == PNG_COLOR_TYPE_PALETTE */
1717
1718
         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1719
         else /* color_type != PNG_COLOR_TYPE_PALETTE */
1720
         {
1721
            int gs_sig, g_sig;
1722
            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
1723
            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
1724
1725
            switch (png_ptr->background_gamma_type)
1726
            {
1727
               case PNG_BACKGROUND_GAMMA_SCREEN:
1728
                  g = png_ptr->screen_gamma;
1729
                  /* gs = PNG_FP_1; */
1730
                  break;
1731
1732
               case PNG_BACKGROUND_GAMMA_FILE:
1733
                  g = png_reciprocal(png_ptr->colorspace.gamma);
1734
                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
1735
                      png_ptr->screen_gamma);
1736
                  break;
1737
1738
               case PNG_BACKGROUND_GAMMA_UNIQUE:
1739
                  g = png_reciprocal(png_ptr->background_gamma);
1740
                  gs = png_reciprocal2(png_ptr->background_gamma,
1741
                      png_ptr->screen_gamma);
1742
                  break;
1743
1744
               default:
1745
                  png_error(png_ptr, "invalid background gamma type");
1746
            }
1747
1748
            g_sig = png_gamma_significant(g);
1749
            gs_sig = png_gamma_significant(gs);
1750
1751
            if (g_sig != 0)
1752
               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
1753
                   png_ptr->background.gray, g);
1754
1755
            if (gs_sig != 0)
1756
               png_ptr->background.gray = png_gamma_correct(png_ptr,
1757
                   png_ptr->background.gray, gs);
1758
1759
            if ((png_ptr->background.red != png_ptr->background.green) ||
1760
                (png_ptr->background.red != png_ptr->background.blue) ||
1761
                (png_ptr->background.red != png_ptr->background.gray))
1762
            {
1763
               /* RGB or RGBA with color background */
1764
               if (g_sig != 0)
1765
               {
1766
                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
1767
                      png_ptr->background.red, g);
1768
1769
                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
1770
                      png_ptr->background.green, g);
1771
1772
                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
1773
                      png_ptr->background.blue, g);
1774
               }
1775
1776
               if (gs_sig != 0)
1777
               {
1778
                  png_ptr->background.red = png_gamma_correct(png_ptr,
1779
                      png_ptr->background.red, gs);
1780
1781
                  png_ptr->background.green = png_gamma_correct(png_ptr,
1782
                      png_ptr->background.green, gs);
1783
1784
                  png_ptr->background.blue = png_gamma_correct(png_ptr,
1785
                      png_ptr->background.blue, gs);
1786
               }
1787
            }
1788
1789
            else
1790
            {
1791
               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1792
               png_ptr->background_1.red = png_ptr->background_1.green
1793
                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
1794
1795
               png_ptr->background.red = png_ptr->background.green
1796
                   = png_ptr->background.blue = png_ptr->background.gray;
1797
            }
1798
1799
            /* The background is now in screen gamma: */
1800
            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
1801
         } /* color_type != PNG_COLOR_TYPE_PALETTE */
1802
      }/* png_ptr->transformations & PNG_BACKGROUND */
1803
1804
      else
1805
      /* Transformation does not include PNG_BACKGROUND */
1806
#endif /* READ_BACKGROUND */
1807
0
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
1808
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1809
         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
1810
         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
1811
         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
1812
#endif
1813
         )
1814
0
      {
1815
0
         png_colorp palette = png_ptr->palette;
1816
0
         int num_palette = png_ptr->num_palette;
1817
0
         int i;
1818
0
1819
0
         /* NOTE: there are other transformations that should probably be in
1820
0
          * here too.
1821
0
          */
1822
0
         for (i = 0; i < num_palette; i++)
1823
0
         {
1824
0
            palette[i].red = png_ptr->gamma_table[palette[i].red];
1825
0
            palette[i].green = png_ptr->gamma_table[palette[i].green];
1826
0
            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1827
0
         }
1828
0
1829
0
         /* Done the gamma correction. */
1830
0
         png_ptr->transformations &= ~PNG_GAMMA;
1831
0
      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
1832
0
   }
1833
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1834
   else
1835
#endif
1836
#endif /* READ_GAMMA */
1837
0
1838
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1839
   /* No GAMMA transformation (see the hanging else 4 lines above) */
1840
   if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1841
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1842
   {
1843
      int i;
1844
      int istop = (int)png_ptr->num_trans;
1845
      png_color back;
1846
      png_colorp palette = png_ptr->palette;
1847
1848
      back.red   = (png_byte)png_ptr->background.red;
1849
      back.green = (png_byte)png_ptr->background.green;
1850
      back.blue  = (png_byte)png_ptr->background.blue;
1851
1852
      for (i = 0; i < istop; i++)
1853
      {
1854
         if (png_ptr->trans_alpha[i] == 0)
1855
         {
1856
            palette[i] = back;
1857
         }
1858
1859
         else if (png_ptr->trans_alpha[i] != 0xff)
1860
         {
1861
            /* The png_composite() macro is defined in png.h */
1862
            png_composite(palette[i].red, palette[i].red,
1863
                png_ptr->trans_alpha[i], back.red);
1864
1865
            png_composite(palette[i].green, palette[i].green,
1866
                png_ptr->trans_alpha[i], back.green);
1867
1868
            png_composite(palette[i].blue, palette[i].blue,
1869
                png_ptr->trans_alpha[i], back.blue);
1870
         }
1871
      }
1872
1873
      png_ptr->transformations &= ~PNG_COMPOSE;
1874
   }
1875
#endif /* READ_BACKGROUND */
1876
1877
#ifdef PNG_READ_SHIFT_SUPPORTED
1878
   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
1879
       (png_ptr->transformations & PNG_EXPAND) == 0 &&
1880
       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1881
   {
1882
      int i;
1883
      int istop = png_ptr->num_palette;
1884
      int shift = 8 - png_ptr->sig_bit.red;
1885
1886
      png_ptr->transformations &= ~PNG_SHIFT;
1887
1888
      /* significant bits can be in the range 1 to 7 for a meaningful result, if
1889
       * the number of significant bits is 0 then no shift is done (this is an
1890
       * error condition which is silently ignored.)
1891
       */
1892
      if (shift > 0 && shift < 8)
1893
         for (i=0; i<istop; ++i)
1894
         {
1895
            int component = png_ptr->palette[i].red;
1896
1897
            component >>= shift;
1898
            png_ptr->palette[i].red = (png_byte)component;
1899
         }
1900
1901
      shift = 8 - png_ptr->sig_bit.green;
1902
      if (shift > 0 && shift < 8)
1903
         for (i=0; i<istop; ++i)
1904
         {
1905
            int component = png_ptr->palette[i].green;
1906
1907
            component >>= shift;
1908
            png_ptr->palette[i].green = (png_byte)component;
1909
         }
1910
1911
      shift = 8 - png_ptr->sig_bit.blue;
1912
      if (shift > 0 && shift < 8)
1913
         for (i=0; i<istop; ++i)
1914
         {
1915
            int component = png_ptr->palette[i].blue;
1916
1917
            component >>= shift;
1918
            png_ptr->palette[i].blue = (png_byte)component;
1919
         }
1920
   }
1921
#endif /* READ_SHIFT */
1922
}
1923
1924
/* Modify the info structure to reflect the transformations.  The
1925
 * info should be updated so a PNG file could be written with it,
1926
 * assuming the transformations result in valid PNG data.
1927
 */
1928
void /* PRIVATE */
1929
png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
1930
0
{
1931
0
   png_debug(1, "in png_read_transform_info");
1932
0
1933
0
#ifdef PNG_READ_EXPAND_SUPPORTED
1934
0
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
1935
0
   {
1936
0
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1937
0
      {
1938
0
         /* This check must match what actually happens in
1939
0
          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1940
0
          * it is all opaque we must do the same (at present it does not.)
1941
0
          */
1942
0
         if (png_ptr->num_trans > 0)
1943
0
            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1944
0
1945
0
         else
1946
0
            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1947
0
1948
0
         info_ptr->bit_depth = 8;
1949
0
         info_ptr->num_trans = 0;
1950
0
1951
0
         if (png_ptr->palette == NULL)
1952
0
            png_error (png_ptr, "Palette is NULL in indexed image");
1953
0
      }
1954
0
      else
1955
0
      {
1956
0
         if (png_ptr->num_trans != 0)
1957
0
         {
1958
0
            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1959
0
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1960
0
         }
1961
0
         if (info_ptr->bit_depth < 8)
1962
0
            info_ptr->bit_depth = 8;
1963
0
1964
0
         info_ptr->num_trans = 0;
1965
0
      }
1966
0
   }
1967
0
#endif
1968
0
1969
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
1970
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
1971
   /* The following is almost certainly wrong unless the background value is in
1972
    * the screen space!
1973
    */
1974
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1975
      info_ptr->background = png_ptr->background;
1976
#endif
1977
1978
0
#ifdef PNG_READ_GAMMA_SUPPORTED
1979
0
   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1980
0
    * however it seems that the code in png_init_read_transformations, which has
1981
0
    * been called before this from png_read_update_info->png_read_start_row
1982
0
    * sometimes does the gamma transform and cancels the flag.
1983
0
    *
1984
0
    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
1985
0
    * the screen_gamma value.  The following probably results in weirdness if
1986
0
    * the info_ptr is used by the app after the rows have been read.
1987
0
    */
1988
0
   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1989
0
#endif
1990
0
1991
0
   if (info_ptr->bit_depth == 16)
1992
0
   {
1993
0
#  ifdef PNG_READ_16BIT_SUPPORTED
1994
0
#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1995
0
         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
1996
0
            info_ptr->bit_depth = 8;
1997
0
#     endif
1998
0
1999
#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2000
         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
2001
            info_ptr->bit_depth = 8;
2002
#     endif
2003
2004
#  else
2005
      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2006
       * the app program can chose if both APIs are available by setting the
2007
       * correct scaling to use.
2008
       */
2009
#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2010
         /* For compatibility with previous versions use the strip method by
2011
          * default.  This code works because if PNG_SCALE_16_TO_8 is already
2012
          * set the code below will do that in preference to the chop.
2013
          */
2014
         png_ptr->transformations |= PNG_16_TO_8;
2015
         info_ptr->bit_depth = 8;
2016
#     else
2017
2018
#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2019
            png_ptr->transformations |= PNG_SCALE_16_TO_8;
2020
            info_ptr->bit_depth = 8;
2021
#        else
2022
2023
            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
2024
#        endif
2025
#    endif
2026
#endif /* !READ_16BIT */
2027
   }
2028
0
2029
0
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2030
0
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2031
0
      info_ptr->color_type = (png_byte)(info_ptr->color_type |
2032
0
         PNG_COLOR_MASK_COLOR);
2033
0
#endif
2034
0
2035
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2036
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
2037
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2038
         ~PNG_COLOR_MASK_COLOR);
2039
#endif
2040
2041
#ifdef PNG_READ_QUANTIZE_SUPPORTED
2042
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
2043
   {
2044
      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2045
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2046
          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
2047
      {
2048
         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
2049
      }
2050
   }
2051
#endif
2052
2053
#ifdef PNG_READ_EXPAND_16_SUPPORTED
2054
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
2055
       info_ptr->bit_depth == 8 &&
2056
       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2057
   {
2058
      info_ptr->bit_depth = 16;
2059
   }
2060
#endif
2061
2062
#ifdef PNG_READ_PACK_SUPPORTED
2063
   if ((png_ptr->transformations & PNG_PACK) != 0 &&
2064
       (info_ptr->bit_depth < 8))
2065
      info_ptr->bit_depth = 8;
2066
#endif
2067
2068
0
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2069
0
      info_ptr->channels = 1;
2070
0
2071
0
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
2072
0
      info_ptr->channels = 3;
2073
0
2074
0
   else
2075
0
      info_ptr->channels = 1;
2076
0
2077
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2078
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2079
   {
2080
      info_ptr->color_type = (png_byte)(info_ptr->color_type &
2081
         ~PNG_COLOR_MASK_ALPHA);
2082
      info_ptr->num_trans = 0;
2083
   }
2084
#endif
2085
2086
0
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2087
0
      info_ptr->channels++;
2088
0
2089
#ifdef PNG_READ_FILLER_SUPPORTED
2090
   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
2091
   if ((png_ptr->transformations & PNG_FILLER) != 0 &&
2092
       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
2093
       info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
2094
   {
2095
      info_ptr->channels++;
2096
      /* If adding a true alpha channel not just filler */
2097
      if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
2098
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2099
   }
2100
#endif
2101
2102
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
2103
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2104
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2105
   {
2106
      if (png_ptr->user_transform_depth != 0)
2107
         info_ptr->bit_depth = png_ptr->user_transform_depth;
2108
2109
      if (png_ptr->user_transform_channels != 0)
2110
         info_ptr->channels = png_ptr->user_transform_channels;
2111
   }
2112
#endif
2113
2114
0
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2115
0
       info_ptr->bit_depth);
2116
0
2117
0
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2118
0
2119
0
   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2120
0
    * check in png_rowbytes that the user buffer won't get overwritten.  Note
2121
0
    * that the field is not always set - if png_read_update_info isn't called
2122
0
    * the application has to either not do any transforms or get the calculation
2123
0
    * right itself.
2124
0
    */
2125
0
   png_ptr->info_rowbytes = info_ptr->rowbytes;
2126
0
2127
#ifndef PNG_READ_EXPAND_SUPPORTED
2128
   if (png_ptr != NULL)
2129
      return;
2130
#endif
2131
}
2132
2133
#ifdef PNG_READ_PACK_SUPPORTED
2134
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
2135
 * without changing the actual values.  Thus, if you had a row with
2136
 * a bit depth of 1, you would end up with bytes that only contained
2137
 * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
2138
 * png_do_shift() after this.
2139
 */
2140
static void
2141
png_do_unpack(png_row_infop row_info, png_bytep row)
2142
{
2143
   png_debug(1, "in png_do_unpack");
2144
2145
   if (row_info->bit_depth < 8)
2146
   {
2147
      png_uint_32 i;
2148
      png_uint_32 row_width=row_info->width;
2149
2150
      switch (row_info->bit_depth)
2151
      {
2152
         case 1:
2153
         {
2154
            png_bytep sp = row + (size_t)((row_width - 1) >> 3);
2155
            png_bytep dp = row + (size_t)row_width - 1;
2156
            png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
2157
            for (i = 0; i < row_width; i++)
2158
            {
2159
               *dp = (png_byte)((*sp >> shift) & 0x01);
2160
2161
               if (shift == 7)
2162
               {
2163
                  shift = 0;
2164
                  sp--;
2165
               }
2166
2167
               else
2168
                  shift++;
2169
2170
               dp--;
2171
            }
2172
            break;
2173
         }
2174
2175
         case 2:
2176
         {
2177
2178
            png_bytep sp = row + (size_t)((row_width - 1) >> 2);
2179
            png_bytep dp = row + (size_t)row_width - 1;
2180
            png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
2181
            for (i = 0; i < row_width; i++)
2182
            {
2183
               *dp = (png_byte)((*sp >> shift) & 0x03);
2184
2185
               if (shift == 6)
2186
               {
2187
                  shift = 0;
2188
                  sp--;
2189
               }
2190
2191
               else
2192
                  shift += 2;
2193
2194
               dp--;
2195
            }
2196
            break;
2197
         }
2198
2199
         case 4:
2200
         {
2201
            png_bytep sp = row + (size_t)((row_width - 1) >> 1);
2202
            png_bytep dp = row + (size_t)row_width - 1;
2203
            png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
2204
            for (i = 0; i < row_width; i++)
2205
            {
2206
               *dp = (png_byte)((*sp >> shift) & 0x0f);
2207
2208
               if (shift == 4)
2209
               {
2210
                  shift = 0;
2211
                  sp--;
2212
               }
2213
2214
               else
2215
                  shift = 4;
2216
2217
               dp--;
2218
            }
2219
            break;
2220
         }
2221
2222
         default:
2223
            break;
2224
      }
2225
      row_info->bit_depth = 8;
2226
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2227
      row_info->rowbytes = row_width * row_info->channels;
2228
   }
2229
}
2230
#endif
2231
2232
#ifdef PNG_READ_SHIFT_SUPPORTED
2233
/* Reverse the effects of png_do_shift.  This routine merely shifts the
2234
 * pixels back to their significant bits values.  Thus, if you have
2235
 * a row of bit depth 8, but only 5 are significant, this will shift
2236
 * the values back to 0 through 31.
2237
 */
2238
static void
2239
png_do_unshift(png_row_infop row_info, png_bytep row,
2240
    png_const_color_8p sig_bits)
2241
{
2242
   int color_type;
2243
2244
   png_debug(1, "in png_do_unshift");
2245
2246
   /* The palette case has already been handled in the _init routine. */
2247
   color_type = row_info->color_type;
2248
2249
   if (color_type != PNG_COLOR_TYPE_PALETTE)
2250
   {
2251
      int shift[4];
2252
      int channels = 0;
2253
      int bit_depth = row_info->bit_depth;
2254
2255
      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
2256
      {
2257
         shift[channels++] = bit_depth - sig_bits->red;
2258
         shift[channels++] = bit_depth - sig_bits->green;
2259
         shift[channels++] = bit_depth - sig_bits->blue;
2260
      }
2261
2262
      else
2263
      {
2264
         shift[channels++] = bit_depth - sig_bits->gray;
2265
      }
2266
2267
      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
2268
      {
2269
         shift[channels++] = bit_depth - sig_bits->alpha;
2270
      }
2271
2272
      {
2273
         int c, have_shift;
2274
2275
         for (c = have_shift = 0; c < channels; ++c)
2276
         {
2277
            /* A shift of more than the bit depth is an error condition but it
2278
             * gets ignored here.
2279
             */
2280
            if (shift[c] <= 0 || shift[c] >= bit_depth)
2281
               shift[c] = 0;
2282
2283
            else
2284
               have_shift = 1;
2285
         }
2286
2287
         if (have_shift == 0)
2288
            return;
2289
      }
2290
2291
      switch (bit_depth)
2292
      {
2293
         default:
2294
         /* Must be 1bpp gray: should not be here! */
2295
            /* NOTREACHED */
2296
            break;
2297
2298
         case 2:
2299
         /* Must be 2bpp gray */
2300
         /* assert(channels == 1 && shift[0] == 1) */
2301
         {
2302
            png_bytep bp = row;
2303
            png_bytep bp_end = bp + row_info->rowbytes;
2304
2305
            while (bp < bp_end)
2306
            {
2307
               int b = (*bp >> 1) & 0x55;
2308
               *bp++ = (png_byte)b;
2309
            }
2310
            break;
2311
         }
2312
2313
         case 4:
2314
         /* Must be 4bpp gray */
2315
         /* assert(channels == 1) */
2316
         {
2317
            png_bytep bp = row;
2318
            png_bytep bp_end = bp + row_info->rowbytes;
2319
            int gray_shift = shift[0];
2320
            int mask =  0xf >> gray_shift;
2321
2322
            mask |= mask << 4;
2323
2324
            while (bp < bp_end)
2325
            {
2326
               int b = (*bp >> gray_shift) & mask;
2327
               *bp++ = (png_byte)b;
2328
            }
2329
            break;
2330
         }
2331
2332
         case 8:
2333
         /* Single byte components, G, GA, RGB, RGBA */
2334
         {
2335
            png_bytep bp = row;
2336
            png_bytep bp_end = bp + row_info->rowbytes;
2337
            int channel = 0;
2338
2339
            while (bp < bp_end)
2340
            {
2341
               int b = *bp >> shift[channel];
2342
               if (++channel >= channels)
2343
                  channel = 0;
2344
               *bp++ = (png_byte)b;
2345
            }
2346
            break;
2347
         }
2348
2349
#ifdef PNG_READ_16BIT_SUPPORTED
2350
         case 16:
2351
         /* Double byte components, G, GA, RGB, RGBA */
2352
         {
2353
            png_bytep bp = row;
2354
            png_bytep bp_end = bp + row_info->rowbytes;
2355
            int channel = 0;
2356
2357
            while (bp < bp_end)
2358
            {
2359
               int value = (bp[0] << 8) + bp[1];
2360
2361
               value >>= shift[channel];
2362
               if (++channel >= channels)
2363
                  channel = 0;
2364
               *bp++ = (png_byte)(value >> 8);
2365
               *bp++ = (png_byte)value;
2366
            }
2367
            break;
2368
         }
2369
#endif
2370
      }
2371
   }
2372
}
2373
#endif
2374
2375
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2376
/* Scale rows of bit depth 16 down to 8 accurately */
2377
static void
2378
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
2379
0
{
2380
0
   png_debug(1, "in png_do_scale_16_to_8");
2381
0
2382
0
   if (row_info->bit_depth == 16)
2383
0
   {
2384
0
      png_bytep sp = row; /* source */
2385
0
      png_bytep dp = row; /* destination */
2386
0
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2387
0
2388
0
      while (sp < ep)
2389
0
      {
2390
0
         /* The input is an array of 16-bit components, these must be scaled to
2391
0
          * 8 bits each.  For a 16-bit value V the required value (from the PNG
2392
0
          * specification) is:
2393
0
          *
2394
0
          *    (V * 255) / 65535
2395
0
          *
2396
0
          * This reduces to round(V / 257), or floor((V + 128.5)/257)
2397
0
          *
2398
0
          * Represent V as the two byte value vhi.vlo.  Make a guess that the
2399
0
          * result is the top byte of V, vhi, then the correction to this value
2400
0
          * is:
2401
0
          *
2402
0
          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
2403
0
          *          = floor(((vlo-vhi) + 128.5) / 257)
2404
0
          *
2405
0
          * This can be approximated using integer arithmetic (and a signed
2406
0
          * shift):
2407
0
          *
2408
0
          *    error = (vlo-vhi+128) >> 8;
2409
0
          *
2410
0
          * The approximate differs from the exact answer only when (vlo-vhi) is
2411
0
          * 128; it then gives a correction of +1 when the exact correction is
2412
0
          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
2413
0
          * input values) is:
2414
0
          *
2415
0
          *    error = (vlo-vhi+128)*65535 >> 24;
2416
0
          *
2417
0
          * An alternative arithmetic calculation which also gives no errors is:
2418
0
          *
2419
0
          *    (V * 255 + 32895) >> 16
2420
0
          */
2421
0
2422
0
         png_int_32 tmp = *sp++; /* must be signed! */
2423
0
         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2424
0
         *dp++ = (png_byte)tmp;
2425
0
      }
2426
0
2427
0
      row_info->bit_depth = 8;
2428
0
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2429
0
      row_info->rowbytes = row_info->width * row_info->channels;
2430
0
   }
2431
0
}
2432
#endif
2433
2434
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2435
static void
2436
/* Simply discard the low byte.  This was the default behavior prior
2437
 * to libpng-1.5.4.
2438
 */
2439
png_do_chop(png_row_infop row_info, png_bytep row)
2440
{
2441
   png_debug(1, "in png_do_chop");
2442
2443
   if (row_info->bit_depth == 16)
2444
   {
2445
      png_bytep sp = row; /* source */
2446
      png_bytep dp = row; /* destination */
2447
      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2448
2449
      while (sp < ep)
2450
      {
2451
         *dp++ = *sp;
2452
         sp += 2; /* skip low byte */
2453
      }
2454
2455
      row_info->bit_depth = 8;
2456
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2457
      row_info->rowbytes = row_info->width * row_info->channels;
2458
   }
2459
}
2460
#endif
2461
2462
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2463
static void
2464
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
2465
{
2466
   png_uint_32 row_width = row_info->width;
2467
2468
   png_debug(1, "in png_do_read_swap_alpha");
2469
2470
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2471
   {
2472
      /* This converts from RGBA to ARGB */
2473
      if (row_info->bit_depth == 8)
2474
      {
2475
         png_bytep sp = row + row_info->rowbytes;
2476
         png_bytep dp = sp;
2477
         png_byte save;
2478
         png_uint_32 i;
2479
2480
         for (i = 0; i < row_width; i++)
2481
         {
2482
            save = *(--sp);
2483
            *(--dp) = *(--sp);
2484
            *(--dp) = *(--sp);
2485
            *(--dp) = *(--sp);
2486
            *(--dp) = save;
2487
         }
2488
      }
2489
2490
#ifdef PNG_READ_16BIT_SUPPORTED
2491
      /* This converts from RRGGBBAA to AARRGGBB */
2492
      else
2493
      {
2494
         png_bytep sp = row + row_info->rowbytes;
2495
         png_bytep dp = sp;
2496
         png_byte save[2];
2497
         png_uint_32 i;
2498
2499
         for (i = 0; i < row_width; i++)
2500
         {
2501
            save[0] = *(--sp);
2502
            save[1] = *(--sp);
2503
            *(--dp) = *(--sp);
2504
            *(--dp) = *(--sp);
2505
            *(--dp) = *(--sp);
2506
            *(--dp) = *(--sp);
2507
            *(--dp) = *(--sp);
2508
            *(--dp) = *(--sp);
2509
            *(--dp) = save[0];
2510
            *(--dp) = save[1];
2511
         }
2512
      }
2513
#endif
2514
   }
2515
2516
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2517
   {
2518
      /* This converts from GA to AG */
2519
      if (row_info->bit_depth == 8)
2520
      {
2521
         png_bytep sp = row + row_info->rowbytes;
2522
         png_bytep dp = sp;
2523
         png_byte save;
2524
         png_uint_32 i;
2525
2526
         for (i = 0; i < row_width; i++)
2527
         {
2528
            save = *(--sp);
2529
            *(--dp) = *(--sp);
2530
            *(--dp) = save;
2531
         }
2532
      }
2533
2534
#ifdef PNG_READ_16BIT_SUPPORTED
2535
      /* This converts from GGAA to AAGG */
2536
      else
2537
      {
2538
         png_bytep sp = row + row_info->rowbytes;
2539
         png_bytep dp = sp;
2540
         png_byte save[2];
2541
         png_uint_32 i;
2542
2543
         for (i = 0; i < row_width; i++)
2544
         {
2545
            save[0] = *(--sp);
2546
            save[1] = *(--sp);
2547
            *(--dp) = *(--sp);
2548
            *(--dp) = *(--sp);
2549
            *(--dp) = save[0];
2550
            *(--dp) = save[1];
2551
         }
2552
      }
2553
#endif
2554
   }
2555
}
2556
#endif
2557
2558
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2559
static void
2560
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
2561
{
2562
   png_uint_32 row_width;
2563
   png_debug(1, "in png_do_read_invert_alpha");
2564
2565
   row_width = row_info->width;
2566
   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2567
   {
2568
      if (row_info->bit_depth == 8)
2569
      {
2570
         /* This inverts the alpha channel in RGBA */
2571
         png_bytep sp = row + row_info->rowbytes;
2572
         png_bytep dp = sp;
2573
         png_uint_32 i;
2574
2575
         for (i = 0; i < row_width; i++)
2576
         {
2577
            *(--dp) = (png_byte)(255 - *(--sp));
2578
2579
/*          This does nothing:
2580
            *(--dp) = *(--sp);
2581
            *(--dp) = *(--sp);
2582
            *(--dp) = *(--sp);
2583
            We can replace it with:
2584
*/
2585
            sp-=3;
2586
            dp=sp;
2587
         }
2588
      }
2589
2590
#ifdef PNG_READ_16BIT_SUPPORTED
2591
      /* This inverts the alpha channel in RRGGBBAA */
2592
      else
2593
      {
2594
         png_bytep sp = row + row_info->rowbytes;
2595
         png_bytep dp = sp;
2596
         png_uint_32 i;
2597
2598
         for (i = 0; i < row_width; i++)
2599
         {
2600
            *(--dp) = (png_byte)(255 - *(--sp));
2601
            *(--dp) = (png_byte)(255 - *(--sp));
2602
2603
/*          This does nothing:
2604
            *(--dp) = *(--sp);
2605
            *(--dp) = *(--sp);
2606
            *(--dp) = *(--sp);
2607
            *(--dp) = *(--sp);
2608
            *(--dp) = *(--sp);
2609
            *(--dp) = *(--sp);
2610
            We can replace it with:
2611
*/
2612
            sp-=6;
2613
            dp=sp;
2614
         }
2615
      }
2616
#endif
2617
   }
2618
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2619
   {
2620
      if (row_info->bit_depth == 8)
2621
      {
2622
         /* This inverts the alpha channel in GA */
2623
         png_bytep sp = row + row_info->rowbytes;
2624
         png_bytep dp = sp;
2625
         png_uint_32 i;
2626
2627
         for (i = 0; i < row_width; i++)
2628
         {
2629
            *(--dp) = (png_byte)(255 - *(--sp));
2630
            *(--dp) = *(--sp);
2631
         }
2632
      }
2633
2634
#ifdef PNG_READ_16BIT_SUPPORTED
2635
      else
2636
      {
2637
         /* This inverts the alpha channel in GGAA */
2638
         png_bytep sp  = row + row_info->rowbytes;
2639
         png_bytep dp = sp;
2640
         png_uint_32 i;
2641
2642
         for (i = 0; i < row_width; i++)
2643
         {
2644
            *(--dp) = (png_byte)(255 - *(--sp));
2645
            *(--dp) = (png_byte)(255 - *(--sp));
2646
/*
2647
            *(--dp) = *(--sp);
2648
            *(--dp) = *(--sp);
2649
*/
2650
            sp-=2;
2651
            dp=sp;
2652
         }
2653
      }
2654
#endif
2655
   }
2656
}
2657
#endif
2658
2659
#ifdef PNG_READ_FILLER_SUPPORTED
2660
/* Add filler channel if we have RGB color */
2661
static void
2662
png_do_read_filler(png_row_infop row_info, png_bytep row,
2663
    png_uint_32 filler, png_uint_32 flags)
2664
{
2665
   png_uint_32 i;
2666
   png_uint_32 row_width = row_info->width;
2667
2668
#ifdef PNG_READ_16BIT_SUPPORTED
2669
   png_byte hi_filler = (png_byte)(filler>>8);
2670
#endif
2671
   png_byte lo_filler = (png_byte)filler;
2672
2673
   png_debug(1, "in png_do_read_filler");
2674
2675
   if (
2676
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
2677
   {
2678
      if (row_info->bit_depth == 8)
2679
      {
2680
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2681
         {
2682
            /* This changes the data from G to GX */
2683
            png_bytep sp = row + (size_t)row_width;
2684
            png_bytep dp =  sp + (size_t)row_width;
2685
            for (i = 1; i < row_width; i++)
2686
            {
2687
               *(--dp) = lo_filler;
2688
               *(--dp) = *(--sp);
2689
            }
2690
            *(--dp) = lo_filler;
2691
            row_info->channels = 2;
2692
            row_info->pixel_depth = 16;
2693
            row_info->rowbytes = row_width * 2;
2694
         }
2695
2696
         else
2697
         {
2698
            /* This changes the data from G to XG */
2699
            png_bytep sp = row + (size_t)row_width;
2700
            png_bytep dp = sp  + (size_t)row_width;
2701
            for (i = 0; i < row_width; i++)
2702
            {
2703
               *(--dp) = *(--sp);
2704
               *(--dp) = lo_filler;
2705
            }
2706
            row_info->channels = 2;
2707
            row_info->pixel_depth = 16;
2708
            row_info->rowbytes = row_width * 2;
2709
         }
2710
      }
2711
2712
#ifdef PNG_READ_16BIT_SUPPORTED
2713
      else if (row_info->bit_depth == 16)
2714
      {
2715
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2716
         {
2717
            /* This changes the data from GG to GGXX */
2718
            png_bytep sp = row + (size_t)row_width * 2;
2719
            png_bytep dp = sp  + (size_t)row_width * 2;
2720
            for (i = 1; i < row_width; i++)
2721
            {
2722
               *(--dp) = lo_filler;
2723
               *(--dp) = hi_filler;
2724
               *(--dp) = *(--sp);
2725
               *(--dp) = *(--sp);
2726
            }
2727
            *(--dp) = lo_filler;
2728
            *(--dp) = hi_filler;
2729
            row_info->channels = 2;
2730
            row_info->pixel_depth = 32;
2731
            row_info->rowbytes = row_width * 4;
2732
         }
2733
2734
         else
2735
         {
2736
            /* This changes the data from GG to XXGG */
2737
            png_bytep sp = row + (size_t)row_width * 2;
2738
            png_bytep dp = sp  + (size_t)row_width * 2;
2739
            for (i = 0; i < row_width; i++)
2740
            {
2741
               *(--dp) = *(--sp);
2742
               *(--dp) = *(--sp);
2743
               *(--dp) = lo_filler;
2744
               *(--dp) = hi_filler;
2745
            }
2746
            row_info->channels = 2;
2747
            row_info->pixel_depth = 32;
2748
            row_info->rowbytes = row_width * 4;
2749
         }
2750
      }
2751
#endif
2752
   } /* COLOR_TYPE == GRAY */
2753
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2754
   {
2755
      if (row_info->bit_depth == 8)
2756
      {
2757
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2758
         {
2759
            /* This changes the data from RGB to RGBX */
2760
            png_bytep sp = row + (size_t)row_width * 3;
2761
            png_bytep dp = sp  + (size_t)row_width;
2762
            for (i = 1; i < row_width; i++)
2763
            {
2764
               *(--dp) = lo_filler;
2765
               *(--dp) = *(--sp);
2766
               *(--dp) = *(--sp);
2767
               *(--dp) = *(--sp);
2768
            }
2769
            *(--dp) = lo_filler;
2770
            row_info->channels = 4;
2771
            row_info->pixel_depth = 32;
2772
            row_info->rowbytes = row_width * 4;
2773
         }
2774
2775
         else
2776
         {
2777
            /* This changes the data from RGB to XRGB */
2778
            png_bytep sp = row + (size_t)row_width * 3;
2779
            png_bytep dp = sp + (size_t)row_width;
2780
            for (i = 0; i < row_width; i++)
2781
            {
2782
               *(--dp) = *(--sp);
2783
               *(--dp) = *(--sp);
2784
               *(--dp) = *(--sp);
2785
               *(--dp) = lo_filler;
2786
            }
2787
            row_info->channels = 4;
2788
            row_info->pixel_depth = 32;
2789
            row_info->rowbytes = row_width * 4;
2790
         }
2791
      }
2792
2793
#ifdef PNG_READ_16BIT_SUPPORTED
2794
      else if (row_info->bit_depth == 16)
2795
      {
2796
         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2797
         {
2798
            /* This changes the data from RRGGBB to RRGGBBXX */
2799
            png_bytep sp = row + (size_t)row_width * 6;
2800
            png_bytep dp = sp  + (size_t)row_width * 2;
2801
            for (i = 1; i < row_width; i++)
2802
            {
2803
               *(--dp) = lo_filler;
2804
               *(--dp) = hi_filler;
2805
               *(--dp) = *(--sp);
2806
               *(--dp) = *(--sp);
2807
               *(--dp) = *(--sp);
2808
               *(--dp) = *(--sp);
2809
               *(--dp) = *(--sp);
2810
               *(--dp) = *(--sp);
2811
            }
2812
            *(--dp) = lo_filler;
2813
            *(--dp) = hi_filler;
2814
            row_info->channels = 4;
2815
            row_info->pixel_depth = 64;
2816
            row_info->rowbytes = row_width * 8;
2817
         }
2818
2819
         else
2820
         {
2821
            /* This changes the data from RRGGBB to XXRRGGBB */
2822
            png_bytep sp = row + (size_t)row_width * 6;
2823
            png_bytep dp = sp  + (size_t)row_width * 2;
2824
            for (i = 0; i < row_width; i++)
2825
            {
2826
               *(--dp) = *(--sp);
2827
               *(--dp) = *(--sp);
2828
               *(--dp) = *(--sp);
2829
               *(--dp) = *(--sp);
2830
               *(--dp) = *(--sp);
2831
               *(--dp) = *(--sp);
2832
               *(--dp) = lo_filler;
2833
               *(--dp) = hi_filler;
2834
            }
2835
2836
            row_info->channels = 4;
2837
            row_info->pixel_depth = 64;
2838
            row_info->rowbytes = row_width * 8;
2839
         }
2840
      }
2841
#endif
2842
   } /* COLOR_TYPE == RGB */
2843
}
2844
#endif
2845
2846
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2847
/* Expand grayscale files to RGB, with or without alpha */
2848
static void
2849
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2850
0
{
2851
0
   png_uint_32 i;
2852
0
   png_uint_32 row_width = row_info->width;
2853
0
2854
0
   png_debug(1, "in png_do_gray_to_rgb");
2855
0
2856
0
   if (row_info->bit_depth >= 8 &&
2857
0
       (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
2858
0
   {
2859
0
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2860
0
      {
2861
0
         if (row_info->bit_depth == 8)
2862
0
         {
2863
0
            /* This changes G to RGB */
2864
0
            png_bytep sp = row + (size_t)row_width - 1;
2865
0
            png_bytep dp = sp  + (size_t)row_width * 2;
2866
0
            for (i = 0; i < row_width; i++)
2867
0
            {
2868
0
               *(dp--) = *sp;
2869
0
               *(dp--) = *sp;
2870
0
               *(dp--) = *(sp--);
2871
0
            }
2872
0
         }
2873
0
2874
0
         else
2875
0
         {
2876
0
            /* This changes GG to RRGGBB */
2877
0
            png_bytep sp = row + (size_t)row_width * 2 - 1;
2878
0
            png_bytep dp = sp  + (size_t)row_width * 4;
2879
0
            for (i = 0; i < row_width; i++)
2880
0
            {
2881
0
               *(dp--) = *sp;
2882
0
               *(dp--) = *(sp - 1);
2883
0
               *(dp--) = *sp;
2884
0
               *(dp--) = *(sp - 1);
2885
0
               *(dp--) = *(sp--);
2886
0
               *(dp--) = *(sp--);
2887
0
            }
2888
0
         }
2889
0
      }
2890
0
2891
0
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2892
0
      {
2893
0
         if (row_info->bit_depth == 8)
2894
0
         {
2895
0
            /* This changes GA to RGBA */
2896
0
            png_bytep sp = row + (size_t)row_width * 2 - 1;
2897
0
            png_bytep dp = sp  + (size_t)row_width * 2;
2898
0
            for (i = 0; i < row_width; i++)
2899
0
            {
2900
0
               *(dp--) = *(sp--);
2901
0
               *(dp--) = *sp;
2902
0
               *(dp--) = *sp;
2903
0
               *(dp--) = *(sp--);
2904
0
            }
2905
0
         }
2906
0
2907
0
         else
2908
0
         {
2909
0
            /* This changes GGAA to RRGGBBAA */
2910
0
            png_bytep sp = row + (size_t)row_width * 4 - 1;
2911
0
            png_bytep dp = sp  + (size_t)row_width * 4;
2912
0
            for (i = 0; i < row_width; i++)
2913
0
            {
2914
0
               *(dp--) = *(sp--);
2915
0
               *(dp--) = *(sp--);
2916
0
               *(dp--) = *sp;
2917
0
               *(dp--) = *(sp - 1);
2918
0
               *(dp--) = *sp;
2919
0
               *(dp--) = *(sp - 1);
2920
0
               *(dp--) = *(sp--);
2921
0
               *(dp--) = *(sp--);
2922
0
            }
2923
0
         }
2924
0
      }
2925
0
      row_info->channels = (png_byte)(row_info->channels + 2);
2926
0
      row_info->color_type |= PNG_COLOR_MASK_COLOR;
2927
0
      row_info->pixel_depth = (png_byte)(row_info->channels *
2928
0
          row_info->bit_depth);
2929
0
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2930
0
   }
2931
0
}
2932
#endif
2933
2934
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2935
/* Reduce RGB files to grayscale, with or without alpha
2936
 * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
2937
 * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
2938
 * versions dated 1998 through November 2002 have been archived at
2939
 * https://web.archive.org/web/20000816232553/www.inforamp.net/
2940
 * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2941
 * Charles Poynton poynton at poynton.com
2942
 *
2943
 *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2944
 *
2945
 *  which can be expressed with integers as
2946
 *
2947
 *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2948
 *
2949
 * Poynton's current link (as of January 2003 through July 2011):
2950
 * <http://www.poynton.com/notes/colour_and_gamma/>
2951
 * has changed the numbers slightly:
2952
 *
2953
 *     Y = 0.2126*R + 0.7152*G + 0.0722*B
2954
 *
2955
 *  which can be expressed with integers as
2956
 *
2957
 *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
2958
 *
2959
 *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
2960
 *  end point chromaticities and the D65 white point.  Depending on the
2961
 *  precision used for the D65 white point this produces a variety of different
2962
 *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
2963
 *  used (0.3127,0.3290) the Y calculation would be:
2964
 *
2965
 *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
2966
 *
2967
 *  While this is correct the rounding results in an overflow for white, because
2968
 *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
2969
 *  libpng uses, instead, the closest non-overflowing approximation:
2970
 *
2971
 *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
2972
 *
2973
 *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
2974
 *  (including an sRGB chunk) then the chromaticities are used to calculate the
2975
 *  coefficients.  See the chunk handling in pngrutil.c for more information.
2976
 *
2977
 *  In all cases the calculation is to be done in a linear colorspace.  If no
2978
 *  gamma information is available to correct the encoding of the original RGB
2979
 *  values this results in an implicit assumption that the original PNG RGB
2980
 *  values were linear.
2981
 *
2982
 *  Other integer coefficients can be used via png_set_rgb_to_gray().  Because
2983
 *  the API takes just red and green coefficients the blue coefficient is
2984
 *  calculated to make the sum 32768.  This will result in different rounding
2985
 *  to that used above.
2986
 */
2987
static int
2988
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2989
2990
{
2991
   int rgb_error = 0;
2992
2993
   png_debug(1, "in png_do_rgb_to_gray");
2994
2995
   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
2996
       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
2997
   {
2998
      PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2999
      PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
3000
      PNG_CONST png_uint_32 bc = 32768 - rc - gc;
3001
      PNG_CONST png_uint_32 row_width = row_info->width;
3002
      PNG_CONST int have_alpha =
3003
         (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3004
3005
      if (row_info->bit_depth == 8)
3006
      {
3007
#ifdef PNG_READ_GAMMA_SUPPORTED
3008
         /* Notice that gamma to/from 1 are not necessarily inverses (if
3009
          * there is an overall gamma correction).  Prior to 1.5.5 this code
3010
          * checked the linearized values for equality; this doesn't match
3011
          * the documentation, the original values must be checked.
3012
          */
3013
         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3014
         {
3015
            png_bytep sp = row;
3016
            png_bytep dp = row;
3017
            png_uint_32 i;
3018
3019
            for (i = 0; i < row_width; i++)
3020
            {
3021
               png_byte red   = *(sp++);
3022
               png_byte green = *(sp++);
3023
               png_byte blue  = *(sp++);
3024
3025
               if (red != green || red != blue)
3026
               {
3027
                  red = png_ptr->gamma_to_1[red];
3028
                  green = png_ptr->gamma_to_1[green];
3029
                  blue = png_ptr->gamma_to_1[blue];
3030
3031
                  rgb_error |= 1;
3032
                  *(dp++) = png_ptr->gamma_from_1[
3033
                      (rc*red + gc*green + bc*blue + 16384)>>15];
3034
               }
3035
3036
               else
3037
               {
3038
                  /* If there is no overall correction the table will not be
3039
                   * set.
3040
                   */
3041
                  if (png_ptr->gamma_table != NULL)
3042
                     red = png_ptr->gamma_table[red];
3043
3044
                  *(dp++) = red;
3045
               }
3046
3047
               if (have_alpha != 0)
3048
                  *(dp++) = *(sp++);
3049
            }
3050
         }
3051
         else
3052
#endif
3053
         {
3054
            png_bytep sp = row;
3055
            png_bytep dp = row;
3056
            png_uint_32 i;
3057
3058
            for (i = 0; i < row_width; i++)
3059
            {
3060
               png_byte red   = *(sp++);
3061
               png_byte green = *(sp++);
3062
               png_byte blue  = *(sp++);
3063
3064
               if (red != green || red != blue)
3065
               {
3066
                  rgb_error |= 1;
3067
                  /* NOTE: this is the historical approach which simply
3068
                   * truncates the results.
3069
                   */
3070
                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3071
               }
3072
3073
               else
3074
                  *(dp++) = red;
3075
3076
               if (have_alpha != 0)
3077
                  *(dp++) = *(sp++);
3078
            }
3079
         }
3080
      }
3081
3082
      else /* RGB bit_depth == 16 */
3083
      {
3084
#ifdef PNG_READ_GAMMA_SUPPORTED
3085
         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
3086
         {
3087
            png_bytep sp = row;
3088
            png_bytep dp = row;
3089
            png_uint_32 i;
3090
3091
            for (i = 0; i < row_width; i++)
3092
            {
3093
               png_uint_16 red, green, blue, w;
3094
               png_byte hi,lo;
3095
3096
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
3097
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
3098
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3099
3100
               if (red == green && red == blue)
3101
               {
3102
                  if (png_ptr->gamma_16_table != NULL)
3103
                     w = png_ptr->gamma_16_table[(red & 0xff)
3104
                         >> png_ptr->gamma_shift][red >> 8];
3105
3106
                  else
3107
                     w = red;
3108
               }
3109
3110
               else
3111
               {
3112
                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red & 0xff)
3113
                      >> png_ptr->gamma_shift][red>>8];
3114
                  png_uint_16 green_1 =
3115
                      png_ptr->gamma_16_to_1[(green & 0xff) >>
3116
                      png_ptr->gamma_shift][green>>8];
3117
                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue & 0xff)
3118
                      >> png_ptr->gamma_shift][blue>>8];
3119
                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
3120
                      + bc*blue_1 + 16384)>>15);
3121
                  w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
3122
                      png_ptr->gamma_shift][gray16 >> 8];
3123
                  rgb_error |= 1;
3124
               }
3125
3126
               *(dp++) = (png_byte)((w>>8) & 0xff);
3127
               *(dp++) = (png_byte)(w & 0xff);
3128
3129
               if (have_alpha != 0)
3130
               {
3131
                  *(dp++) = *(sp++);
3132
                  *(dp++) = *(sp++);
3133
               }
3134
            }
3135
         }
3136
         else
3137
#endif
3138
         {
3139
            png_bytep sp = row;
3140
            png_bytep dp = row;
3141
            png_uint_32 i;
3142
3143
            for (i = 0; i < row_width; i++)
3144
            {
3145
               png_uint_16 red, green, blue, gray16;
3146
               png_byte hi,lo;
3147
3148
               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
3149
               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
3150
               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
3151
3152
               if (red != green || red != blue)
3153
                  rgb_error |= 1;
3154
3155
               /* From 1.5.5 in the 16-bit case do the accurate conversion even
3156
                * in the 'fast' case - this is because this is where the code
3157
                * ends up when handling linear 16-bit data.
3158
                */
3159
               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
3160
                  15);
3161
               *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
3162
               *(dp++) = (png_byte)(gray16 & 0xff);
3163
3164
               if (have_alpha != 0)
3165
               {
3166
                  *(dp++) = *(sp++);
3167
                  *(dp++) = *(sp++);
3168
               }
3169
            }
3170
         }
3171
      }
3172
3173
      row_info->channels = (png_byte)(row_info->channels - 2);
3174
      row_info->color_type = (png_byte)(row_info->color_type &
3175
          ~PNG_COLOR_MASK_COLOR);
3176
      row_info->pixel_depth = (png_byte)(row_info->channels *
3177
          row_info->bit_depth);
3178
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3179
   }
3180
   return rgb_error;
3181
}
3182
#endif
3183
3184
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
3185
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
3186
/* Replace any alpha or transparency with the supplied background color.
3187
 * "background" is already in the screen gamma, while "background_1" is
3188
 * at a gamma of 1.0.  Paletted files have already been taken care of.
3189
 */
3190
static void
3191
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3192
{
3193
#ifdef PNG_READ_GAMMA_SUPPORTED
3194
   png_const_bytep gamma_table = png_ptr->gamma_table;
3195
   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
3196
   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
3197
   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
3198
   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
3199
   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
3200
   int gamma_shift = png_ptr->gamma_shift;
3201
   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3202
#endif
3203
3204
   png_bytep sp;
3205
   png_uint_32 i;
3206
   png_uint_32 row_width = row_info->width;
3207
   int shift;
3208
3209
   png_debug(1, "in png_do_compose");
3210
3211
   switch (row_info->color_type)
3212
   {
3213
      case PNG_COLOR_TYPE_GRAY:
3214
      {
3215
         switch (row_info->bit_depth)
3216
         {
3217
            case 1:
3218
            {
3219
               sp = row;
3220
               shift = 7;
3221
               for (i = 0; i < row_width; i++)
3222
               {
3223
                  if ((png_uint_16)((*sp >> shift) & 0x01)
3224
                     == png_ptr->trans_color.gray)
3225
                  {
3226
                     unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
3227
                     tmp |=
3228
                         (unsigned int)(png_ptr->background.gray << shift);
3229
                     *sp = (png_byte)(tmp & 0xff);
3230
                  }
3231
3232
                  if (shift == 0)
3233
                  {
3234
                     shift = 7;
3235
                     sp++;
3236
                  }
3237
3238
                  else
3239
                     shift--;
3240
               }
3241
               break;
3242
            }
3243
3244
            case 2:
3245
            {
3246
#ifdef PNG_READ_GAMMA_SUPPORTED
3247
               if (gamma_table != NULL)
3248
               {
3249
                  sp = row;
3250
                  shift = 6;
3251
                  for (i = 0; i < row_width; i++)
3252
                  {
3253
                     if ((png_uint_16)((*sp >> shift) & 0x03)
3254
                         == png_ptr->trans_color.gray)
3255
                     {
3256
                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3257
                        tmp |=
3258
                           (unsigned int)png_ptr->background.gray << shift;
3259
                        *sp = (png_byte)(tmp & 0xff);
3260
                     }
3261
3262
                     else
3263
                     {
3264
                        unsigned int p = (*sp >> shift) & 0x03;
3265
                        unsigned int g = (gamma_table [p | (p << 2) |
3266
                            (p << 4) | (p << 6)] >> 6) & 0x03;
3267
                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3268
                        tmp |= (unsigned int)(g << shift);
3269
                        *sp = (png_byte)(tmp & 0xff);
3270
                     }
3271
3272
                     if (shift == 0)
3273
                     {
3274
                        shift = 6;
3275
                        sp++;
3276
                     }
3277
3278
                     else
3279
                        shift -= 2;
3280
                  }
3281
               }
3282
3283
               else
3284
#endif
3285
               {
3286
                  sp = row;
3287
                  shift = 6;
3288
                  for (i = 0; i < row_width; i++)
3289
                  {
3290
                     if ((png_uint_16)((*sp >> shift) & 0x03)
3291
                         == png_ptr->trans_color.gray)
3292
                     {
3293
                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3294
                        tmp |=
3295
                            (unsigned int)png_ptr->background.gray << shift;
3296
                        *sp = (png_byte)(tmp & 0xff);
3297
                     }
3298
3299
                     if (shift == 0)
3300
                     {
3301
                        shift = 6;
3302
                        sp++;
3303
                     }
3304
3305
                     else
3306
                        shift -= 2;
3307
                  }
3308
               }
3309
               break;
3310
            }
3311
3312
            case 4:
3313
            {
3314
#ifdef PNG_READ_GAMMA_SUPPORTED
3315
               if (gamma_table != NULL)
3316
               {
3317
                  sp = row;
3318
                  shift = 4;
3319
                  for (i = 0; i < row_width; i++)
3320
                  {
3321
                     if ((png_uint_16)((*sp >> shift) & 0x0f)
3322
                         == png_ptr->trans_color.gray)
3323
                     {
3324
                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3325
                        tmp |=
3326
                           (unsigned int)(png_ptr->background.gray << shift);
3327
                        *sp = (png_byte)(tmp & 0xff);
3328
                     }
3329
3330
                     else
3331
                     {
3332
                        unsigned int p = (*sp >> shift) & 0x0f;
3333
                        unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
3334
                           0x0f;
3335
                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3336
                        tmp |= (unsigned int)(g << shift);
3337
                        *sp = (png_byte)(tmp & 0xff);
3338
                     }
3339
3340
                     if (shift == 0)
3341
                     {
3342
                        shift = 4;
3343
                        sp++;
3344
                     }
3345
3346
                     else
3347
                        shift -= 4;
3348
                  }
3349
               }
3350
3351
               else
3352
#endif
3353
               {
3354
                  sp = row;
3355
                  shift = 4;
3356
                  for (i = 0; i < row_width; i++)
3357
                  {
3358
                     if ((png_uint_16)((*sp >> shift) & 0x0f)
3359
                         == png_ptr->trans_color.gray)
3360
                     {
3361
                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3362
                        tmp |=
3363
                           (unsigned int)(png_ptr->background.gray << shift);
3364
                        *sp = (png_byte)(tmp & 0xff);
3365
                     }
3366
3367
                     if (shift == 0)
3368
                     {
3369
                        shift = 4;
3370
                        sp++;
3371
                     }
3372
3373
                     else
3374
                        shift -= 4;
3375
                  }
3376
               }
3377
               break;
3378
            }
3379
3380
            case 8:
3381
            {
3382
#ifdef PNG_READ_GAMMA_SUPPORTED
3383
               if (gamma_table != NULL)
3384
               {
3385
                  sp = row;
3386
                  for (i = 0; i < row_width; i++, sp++)
3387
                  {
3388
                     if (*sp == png_ptr->trans_color.gray)
3389
                        *sp = (png_byte)png_ptr->background.gray;
3390
3391
                     else
3392
                        *sp = gamma_table[*sp];
3393
                  }
3394
               }
3395
               else
3396
#endif
3397
               {
3398
                  sp = row;
3399
                  for (i = 0; i < row_width; i++, sp++)
3400
                  {
3401
                     if (*sp == png_ptr->trans_color.gray)
3402
                        *sp = (png_byte)png_ptr->background.gray;
3403
                  }
3404
               }
3405
               break;
3406
            }
3407
3408
            case 16:
3409
            {
3410
#ifdef PNG_READ_GAMMA_SUPPORTED
3411
               if (gamma_16 != NULL)
3412
               {
3413
                  sp = row;
3414
                  for (i = 0; i < row_width; i++, sp += 2)
3415
                  {
3416
                     png_uint_16 v;
3417
3418
                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3419
3420
                     if (v == png_ptr->trans_color.gray)
3421
                     {
3422
                        /* Background is already in screen gamma */
3423
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3424
                             & 0xff);
3425
                        *(sp + 1) = (png_byte)(png_ptr->background.gray
3426
                             & 0xff);
3427
                     }
3428
3429
                     else
3430
                     {
3431
                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3432
                        *sp = (png_byte)((v >> 8) & 0xff);
3433
                        *(sp + 1) = (png_byte)(v & 0xff);
3434
                     }
3435
                  }
3436
               }
3437
               else
3438
#endif
3439
               {
3440
                  sp = row;
3441
                  for (i = 0; i < row_width; i++, sp += 2)
3442
                  {
3443
                     png_uint_16 v;
3444
3445
                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3446
3447
                     if (v == png_ptr->trans_color.gray)
3448
                     {
3449
                        *sp = (png_byte)((png_ptr->background.gray >> 8)
3450
                             & 0xff);
3451
                        *(sp + 1) = (png_byte)(png_ptr->background.gray
3452
                             & 0xff);
3453
                     }
3454
                  }
3455
               }
3456
               break;
3457
            }
3458
3459
            default:
3460
               break;
3461
         }
3462
         break;
3463
      }
3464
3465
      case PNG_COLOR_TYPE_RGB:
3466
      {
3467
         if (row_info->bit_depth == 8)
3468
         {
3469
#ifdef PNG_READ_GAMMA_SUPPORTED
3470
            if (gamma_table != NULL)
3471
            {
3472
               sp = row;
3473
               for (i = 0; i < row_width; i++, sp += 3)
3474
               {
3475
                  if (*sp == png_ptr->trans_color.red &&
3476
                      *(sp + 1) == png_ptr->trans_color.green &&
3477
                      *(sp + 2) == png_ptr->trans_color.blue)
3478
                  {
3479
                     *sp = (png_byte)png_ptr->background.red;
3480
                     *(sp + 1) = (png_byte)png_ptr->background.green;
3481
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
3482
                  }
3483
3484
                  else
3485
                  {
3486
                     *sp = gamma_table[*sp];
3487
                     *(sp + 1) = gamma_table[*(sp + 1)];
3488
                     *(sp + 2) = gamma_table[*(sp + 2)];
3489
                  }
3490
               }
3491
            }
3492
            else
3493
#endif
3494
            {
3495
               sp = row;
3496
               for (i = 0; i < row_width; i++, sp += 3)
3497
               {
3498
                  if (*sp == png_ptr->trans_color.red &&
3499
                      *(sp + 1) == png_ptr->trans_color.green &&
3500
                      *(sp + 2) == png_ptr->trans_color.blue)
3501
                  {
3502
                     *sp = (png_byte)png_ptr->background.red;
3503
                     *(sp + 1) = (png_byte)png_ptr->background.green;
3504
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
3505
                  }
3506
               }
3507
            }
3508
         }
3509
         else /* if (row_info->bit_depth == 16) */
3510
         {
3511
#ifdef PNG_READ_GAMMA_SUPPORTED
3512
            if (gamma_16 != NULL)
3513
            {
3514
               sp = row;
3515
               for (i = 0; i < row_width; i++, sp += 6)
3516
               {
3517
                  png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3518
3519
                  png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3520
                      + *(sp + 3));
3521
3522
                  png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3523
                      + *(sp + 5));
3524
3525
                  if (r == png_ptr->trans_color.red &&
3526
                      g == png_ptr->trans_color.green &&
3527
                      b == png_ptr->trans_color.blue)
3528
                  {
3529
                     /* Background is already in screen gamma */
3530
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3531
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3532
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3533
                             & 0xff);
3534
                     *(sp + 3) = (png_byte)(png_ptr->background.green
3535
                             & 0xff);
3536
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3537
                             & 0xff);
3538
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3539
                  }
3540
3541
                  else
3542
                  {
3543
                     png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3544
                     *sp = (png_byte)((v >> 8) & 0xff);
3545
                     *(sp + 1) = (png_byte)(v & 0xff);
3546
3547
                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3548
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3549
                     *(sp + 3) = (png_byte)(v & 0xff);
3550
3551
                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3552
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3553
                     *(sp + 5) = (png_byte)(v & 0xff);
3554
                  }
3555
               }
3556
            }
3557
3558
            else
3559
#endif
3560
            {
3561
               sp = row;
3562
               for (i = 0; i < row_width; i++, sp += 6)
3563
               {
3564
                  png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3565
3566
                  png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3567
                      + *(sp + 3));
3568
3569
                  png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3570
                      + *(sp + 5));
3571
3572
                  if (r == png_ptr->trans_color.red &&
3573
                      g == png_ptr->trans_color.green &&
3574
                      b == png_ptr->trans_color.blue)
3575
                  {
3576
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3577
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3578
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3579
                             & 0xff);
3580
                     *(sp + 3) = (png_byte)(png_ptr->background.green
3581
                             & 0xff);
3582
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3583
                             & 0xff);
3584
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3585
                  }
3586
               }
3587
            }
3588
         }
3589
         break;
3590
      }
3591
3592
      case PNG_COLOR_TYPE_GRAY_ALPHA:
3593
      {
3594
         if (row_info->bit_depth == 8)
3595
         {
3596
#ifdef PNG_READ_GAMMA_SUPPORTED
3597
            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3598
                gamma_table != NULL)
3599
            {
3600
               sp = row;
3601
               for (i = 0; i < row_width; i++, sp += 2)
3602
               {
3603
                  png_uint_16 a = *(sp + 1);
3604
3605
                  if (a == 0xff)
3606
                     *sp = gamma_table[*sp];
3607
3608
                  else if (a == 0)
3609
                  {
3610
                     /* Background is already in screen gamma */
3611
                     *sp = (png_byte)png_ptr->background.gray;
3612
                  }
3613
3614
                  else
3615
                  {
3616
                     png_byte v, w;
3617
3618
                     v = gamma_to_1[*sp];
3619
                     png_composite(w, v, a, png_ptr->background_1.gray);
3620
                     if (optimize == 0)
3621
                        w = gamma_from_1[w];
3622
                     *sp = w;
3623
                  }
3624
               }
3625
            }
3626
            else
3627
#endif
3628
            {
3629
               sp = row;
3630
               for (i = 0; i < row_width; i++, sp += 2)
3631
               {
3632
                  png_byte a = *(sp + 1);
3633
3634
                  if (a == 0)
3635
                     *sp = (png_byte)png_ptr->background.gray;
3636
3637
                  else if (a < 0xff)
3638
                     png_composite(*sp, *sp, a, png_ptr->background.gray);
3639
               }
3640
            }
3641
         }
3642
         else /* if (png_ptr->bit_depth == 16) */
3643
         {
3644
#ifdef PNG_READ_GAMMA_SUPPORTED
3645
            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3646
                gamma_16_to_1 != NULL)
3647
            {
3648
               sp = row;
3649
               for (i = 0; i < row_width; i++, sp += 4)
3650
               {
3651
                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3652
                      + *(sp + 3));
3653
3654
                  if (a == (png_uint_16)0xffff)
3655
                  {
3656
                     png_uint_16 v;
3657
3658
                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3659
                     *sp = (png_byte)((v >> 8) & 0xff);
3660
                     *(sp + 1) = (png_byte)(v & 0xff);
3661
                  }
3662
3663
                  else if (a == 0)
3664
                  {
3665
                     /* Background is already in screen gamma */
3666
                     *sp = (png_byte)((png_ptr->background.gray >> 8)
3667
                             & 0xff);
3668
                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3669
                  }
3670
3671
                  else
3672
                  {
3673
                     png_uint_16 g, v, w;
3674
3675
                     g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3676
                     png_composite_16(v, g, a, png_ptr->background_1.gray);
3677
                     if (optimize != 0)
3678
                        w = v;
3679
                     else
3680
                        w = gamma_16_from_1[(v & 0xff) >>
3681
                            gamma_shift][v >> 8];
3682
                     *sp = (png_byte)((w >> 8) & 0xff);
3683
                     *(sp + 1) = (png_byte)(w & 0xff);
3684
                  }
3685
               }
3686
            }
3687
            else
3688
#endif
3689
            {
3690
               sp = row;
3691
               for (i = 0; i < row_width; i++, sp += 4)
3692
               {
3693
                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3694
                      + *(sp + 3));
3695
3696
                  if (a == 0)
3697
                  {
3698
                     *sp = (png_byte)((png_ptr->background.gray >> 8)
3699
                             & 0xff);
3700
                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3701
                  }
3702
3703
                  else if (a < 0xffff)
3704
                  {
3705
                     png_uint_16 g, v;
3706
3707
                     g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3708
                     png_composite_16(v, g, a, png_ptr->background.gray);
3709
                     *sp = (png_byte)((v >> 8) & 0xff);
3710
                     *(sp + 1) = (png_byte)(v & 0xff);
3711
                  }
3712
               }
3713
            }
3714
         }
3715
         break;
3716
      }
3717
3718
      case PNG_COLOR_TYPE_RGB_ALPHA:
3719
      {
3720
         if (row_info->bit_depth == 8)
3721
         {
3722
#ifdef PNG_READ_GAMMA_SUPPORTED
3723
            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3724
                gamma_table != NULL)
3725
            {
3726
               sp = row;
3727
               for (i = 0; i < row_width; i++, sp += 4)
3728
               {
3729
                  png_byte a = *(sp + 3);
3730
3731
                  if (a == 0xff)
3732
                  {
3733
                     *sp = gamma_table[*sp];
3734
                     *(sp + 1) = gamma_table[*(sp + 1)];
3735
                     *(sp + 2) = gamma_table[*(sp + 2)];
3736
                  }
3737
3738
                  else if (a == 0)
3739
                  {
3740
                     /* Background is already in screen gamma */
3741
                     *sp = (png_byte)png_ptr->background.red;
3742
                     *(sp + 1) = (png_byte)png_ptr->background.green;
3743
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
3744
                  }
3745
3746
                  else
3747
                  {
3748
                     png_byte v, w;
3749
3750
                     v = gamma_to_1[*sp];
3751
                     png_composite(w, v, a, png_ptr->background_1.red);
3752
                     if (optimize == 0) w = gamma_from_1[w];
3753
                     *sp = w;
3754
3755
                     v = gamma_to_1[*(sp + 1)];
3756
                     png_composite(w, v, a, png_ptr->background_1.green);
3757
                     if (optimize == 0) w = gamma_from_1[w];
3758
                     *(sp + 1) = w;
3759
3760
                     v = gamma_to_1[*(sp + 2)];
3761
                     png_composite(w, v, a, png_ptr->background_1.blue);
3762
                     if (optimize == 0) w = gamma_from_1[w];
3763
                     *(sp + 2) = w;
3764
                  }
3765
               }
3766
            }
3767
            else
3768
#endif
3769
            {
3770
               sp = row;
3771
               for (i = 0; i < row_width; i++, sp += 4)
3772
               {
3773
                  png_byte a = *(sp + 3);
3774
3775
                  if (a == 0)
3776
                  {
3777
                     *sp = (png_byte)png_ptr->background.red;
3778
                     *(sp + 1) = (png_byte)png_ptr->background.green;
3779
                     *(sp + 2) = (png_byte)png_ptr->background.blue;
3780
                  }
3781
3782
                  else if (a < 0xff)
3783
                  {
3784
                     png_composite(*sp, *sp, a, png_ptr->background.red);
3785
3786
                     png_composite(*(sp + 1), *(sp + 1), a,
3787
                         png_ptr->background.green);
3788
3789
                     png_composite(*(sp + 2), *(sp + 2), a,
3790
                         png_ptr->background.blue);
3791
                  }
3792
               }
3793
            }
3794
         }
3795
         else /* if (row_info->bit_depth == 16) */
3796
         {
3797
#ifdef PNG_READ_GAMMA_SUPPORTED
3798
            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3799
                gamma_16_to_1 != NULL)
3800
            {
3801
               sp = row;
3802
               for (i = 0; i < row_width; i++, sp += 8)
3803
               {
3804
                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3805
                      << 8) + (png_uint_16)(*(sp + 7)));
3806
3807
                  if (a == (png_uint_16)0xffff)
3808
                  {
3809
                     png_uint_16 v;
3810
3811
                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3812
                     *sp = (png_byte)((v >> 8) & 0xff);
3813
                     *(sp + 1) = (png_byte)(v & 0xff);
3814
3815
                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3816
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3817
                     *(sp + 3) = (png_byte)(v & 0xff);
3818
3819
                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3820
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3821
                     *(sp + 5) = (png_byte)(v & 0xff);
3822
                  }
3823
3824
                  else if (a == 0)
3825
                  {
3826
                     /* Background is already in screen gamma */
3827
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3828
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3829
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3830
                             & 0xff);
3831
                     *(sp + 3) = (png_byte)(png_ptr->background.green
3832
                             & 0xff);
3833
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3834
                             & 0xff);
3835
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3836
                  }
3837
3838
                  else
3839
                  {
3840
                     png_uint_16 v, w;
3841
3842
                     v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3843
                     png_composite_16(w, v, a, png_ptr->background_1.red);
3844
                     if (optimize == 0)
3845
                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3846
                             8];
3847
                     *sp = (png_byte)((w >> 8) & 0xff);
3848
                     *(sp + 1) = (png_byte)(w & 0xff);
3849
3850
                     v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3851
                     png_composite_16(w, v, a, png_ptr->background_1.green);
3852
                     if (optimize == 0)
3853
                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3854
                             8];
3855
3856
                     *(sp + 2) = (png_byte)((w >> 8) & 0xff);
3857
                     *(sp + 3) = (png_byte)(w & 0xff);
3858
3859
                     v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3860
                     png_composite_16(w, v, a, png_ptr->background_1.blue);
3861
                     if (optimize == 0)
3862
                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3863
                             8];
3864
3865
                     *(sp + 4) = (png_byte)((w >> 8) & 0xff);
3866
                     *(sp + 5) = (png_byte)(w & 0xff);
3867
                  }
3868
               }
3869
            }
3870
3871
            else
3872
#endif
3873
            {
3874
               sp = row;
3875
               for (i = 0; i < row_width; i++, sp += 8)
3876
               {
3877
                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3878
                      << 8) + (png_uint_16)(*(sp + 7)));
3879
3880
                  if (a == 0)
3881
                  {
3882
                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3883
                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3884
                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3885
                             & 0xff);
3886
                     *(sp + 3) = (png_byte)(png_ptr->background.green
3887
                             & 0xff);
3888
                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3889
                             & 0xff);
3890
                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3891
                  }
3892
3893
                  else if (a < 0xffff)
3894
                  {
3895
                     png_uint_16 v;
3896
3897
                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3898
                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3899
                         + *(sp + 3));
3900
                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3901
                         + *(sp + 5));
3902
3903
                     png_composite_16(v, r, a, png_ptr->background.red);
3904
                     *sp = (png_byte)((v >> 8) & 0xff);
3905
                     *(sp + 1) = (png_byte)(v & 0xff);
3906
3907
                     png_composite_16(v, g, a, png_ptr->background.green);
3908
                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3909
                     *(sp + 3) = (png_byte)(v & 0xff);
3910
3911
                     png_composite_16(v, b, a, png_ptr->background.blue);
3912
                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3913
                     *(sp + 5) = (png_byte)(v & 0xff);
3914
                  }
3915
               }
3916
            }
3917
         }
3918
         break;
3919
      }
3920
3921
      default:
3922
         break;
3923
   }
3924
}
3925
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
3926
3927
#ifdef PNG_READ_GAMMA_SUPPORTED
3928
/* Gamma correct the image, avoiding the alpha channel.  Make sure
3929
 * you do this after you deal with the transparency issue on grayscale
3930
 * or RGB images. If your bit depth is 8, use gamma_table, if it
3931
 * is 16, use gamma_16_table and gamma_shift.  Build these with
3932
 * build_gamma_table().
3933
 */
3934
static void
3935
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3936
0
{
3937
0
   png_const_bytep gamma_table = png_ptr->gamma_table;
3938
0
   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
3939
0
   int gamma_shift = png_ptr->gamma_shift;
3940
0
3941
0
   png_bytep sp;
3942
0
   png_uint_32 i;
3943
0
   png_uint_32 row_width=row_info->width;
3944
0
3945
0
   png_debug(1, "in png_do_gamma");
3946
0
3947
0
   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3948
0
       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3949
0
   {
3950
0
      switch (row_info->color_type)
3951
0
      {
3952
0
         case PNG_COLOR_TYPE_RGB:
3953
0
         {
3954
0
            if (row_info->bit_depth == 8)
3955
0
            {
3956
0
               sp = row;
3957
0
               for (i = 0; i < row_width; i++)
3958
0
               {
3959
0
                  *sp = gamma_table[*sp];
3960
0
                  sp++;
3961
0
                  *sp = gamma_table[*sp];
3962
0
                  sp++;
3963
0
                  *sp = gamma_table[*sp];
3964
0
                  sp++;
3965
0
               }
3966
0
            }
3967
0
3968
0
            else /* if (row_info->bit_depth == 16) */
3969
0
            {
3970
0
               sp = row;
3971
0
               for (i = 0; i < row_width; i++)
3972
0
               {
3973
0
                  png_uint_16 v;
3974
0
3975
0
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3976
0
                  *sp = (png_byte)((v >> 8) & 0xff);
3977
0
                  *(sp + 1) = (png_byte)(v & 0xff);
3978
0
                  sp += 2;
3979
0
3980
0
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3981
0
                  *sp = (png_byte)((v >> 8) & 0xff);
3982
0
                  *(sp + 1) = (png_byte)(v & 0xff);
3983
0
                  sp += 2;
3984
0
3985
0
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3986
0
                  *sp = (png_byte)((v >> 8) & 0xff);
3987
0
                  *(sp + 1) = (png_byte)(v & 0xff);
3988
0
                  sp += 2;
3989
0
               }
3990
0
            }
3991
0
            break;
3992
0
         }
3993
0
3994
0
         case PNG_COLOR_TYPE_RGB_ALPHA:
3995
0
         {
3996
0
            if (row_info->bit_depth == 8)
3997
0
            {
3998
0
               sp = row;
3999
0
               for (i = 0; i < row_width; i++)
4000
0
               {
4001
0
                  *sp = gamma_table[*sp];
4002
0
                  sp++;
4003
0
4004
0
                  *sp = gamma_table[*sp];
4005
0
                  sp++;
4006
0
4007
0
                  *sp = gamma_table[*sp];
4008
0
                  sp++;
4009
0
4010
0
                  sp++;
4011
0
               }
4012
0
            }
4013
0
4014
0
            else /* if (row_info->bit_depth == 16) */
4015
0
            {
4016
0
               sp = row;
4017
0
               for (i = 0; i < row_width; i++)
4018
0
               {
4019
0
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4020
0
                  *sp = (png_byte)((v >> 8) & 0xff);
4021
0
                  *(sp + 1) = (png_byte)(v & 0xff);
4022
0
                  sp += 2;
4023
0
4024
0
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4025
0
                  *sp = (png_byte)((v >> 8) & 0xff);
4026
0
                  *(sp + 1) = (png_byte)(v & 0xff);
4027
0
                  sp += 2;
4028
0
4029
0
                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4030
0
                  *sp = (png_byte)((v >> 8) & 0xff);
4031
0
                  *(sp + 1) = (png_byte)(v & 0xff);
4032
0
                  sp += 4;
4033
0
               }
4034
0
            }
4035
0
            break;
4036
0
         }
4037
0
4038
0
         case PNG_COLOR_TYPE_GRAY_ALPHA:
4039
0
         {
4040
0
            if (row_info->bit_depth == 8)
4041
0
            {
4042
0
               sp = row;
4043
0
               for (i = 0; i < row_width; i++)
4044
0
               {
4045
0
                  *sp = gamma_table[*sp];
4046
0
                  sp += 2;
4047
0
               }
4048
0
            }
4049
0
4050
0
            else /* if (row_info->bit_depth == 16) */
4051
0
            {
4052
0
               sp = row;
4053
0
               for (i = 0; i < row_width; i++)
4054
0
               {
4055
0
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4056
0
                  *sp = (png_byte)((v >> 8) & 0xff);
4057
0
                  *(sp + 1) = (png_byte)(v & 0xff);
4058
0
                  sp += 4;
4059
0
               }
4060
0
            }
4061
0
            break;
4062
0
         }
4063
0
4064
0
         case PNG_COLOR_TYPE_GRAY:
4065
0
         {
4066
0
            if (row_info->bit_depth == 2)
4067
0
            {
4068
0
               sp = row;
4069
0
               for (i = 0; i < row_width; i += 4)
4070
0
               {
4071
0
                  int a = *sp & 0xc0;
4072
0
                  int b = *sp & 0x30;
4073
0
                  int c = *sp & 0x0c;
4074
0
                  int d = *sp & 0x03;
4075
0
4076
0
                  *sp = (png_byte)(
4077
0
                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
4078
0
                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
4079
0
                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4080
0
                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4081
0
                  sp++;
4082
0
               }
4083
0
            }
4084
0
4085
0
            if (row_info->bit_depth == 4)
4086
0
            {
4087
0
               sp = row;
4088
0
               for (i = 0; i < row_width; i += 2)
4089
0
               {
4090
0
                  int msb = *sp & 0xf0;
4091
0
                  int lsb = *sp & 0x0f;
4092
0
4093
0
                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4094
0
                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
4095
0
                  sp++;
4096
0
               }
4097
0
            }
4098
0
4099
0
            else if (row_info->bit_depth == 8)
4100
0
            {
4101
0
               sp = row;
4102
0
               for (i = 0; i < row_width; i++)
4103
0
               {
4104
0
                  *sp = gamma_table[*sp];
4105
0
                  sp++;
4106
0
               }
4107
0
            }
4108
0
4109
0
            else if (row_info->bit_depth == 16)
4110
0
            {
4111
0
               sp = row;
4112
0
               for (i = 0; i < row_width; i++)
4113
0
               {
4114
0
                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4115
0
                  *sp = (png_byte)((v >> 8) & 0xff);
4116
0
                  *(sp + 1) = (png_byte)(v & 0xff);
4117
0
                  sp += 2;
4118
0
               }
4119
0
            }
4120
0
            break;
4121
0
         }
4122
0
4123
0
         default:
4124
0
            break;
4125
0
      }
4126
0
   }
4127
0
}
4128
#endif
4129
4130
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4131
/* Encode the alpha channel to the output gamma (the input channel is always
4132
 * linear.)  Called only with color types that have an alpha channel.  Needs the
4133
 * from_1 tables.
4134
 */
4135
static void
4136
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4137
{
4138
   png_uint_32 row_width = row_info->width;
4139
4140
   png_debug(1, "in png_do_encode_alpha");
4141
4142
   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4143
   {
4144
      if (row_info->bit_depth == 8)
4145
      {
4146
         PNG_CONST png_bytep table = png_ptr->gamma_from_1;
4147
4148
         if (table != NULL)
4149
         {
4150
            PNG_CONST int step =
4151
               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4152
4153
            /* The alpha channel is the last component: */
4154
            row += step - 1;
4155
4156
            for (; row_width > 0; --row_width, row += step)
4157
               *row = table[*row];
4158
4159
            return;
4160
         }
4161
      }
4162
4163
      else if (row_info->bit_depth == 16)
4164
      {
4165
         PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
4166
         PNG_CONST int gamma_shift = png_ptr->gamma_shift;
4167
4168
         if (table != NULL)
4169
         {
4170
            PNG_CONST int step =
4171
               (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4172
4173
            /* The alpha channel is the last component: */
4174
            row += step - 2;
4175
4176
            for (; row_width > 0; --row_width, row += step)
4177
            {
4178
               png_uint_16 v;
4179
4180
               v = table[*(row + 1) >> gamma_shift][*row];
4181
               *row = (png_byte)((v >> 8) & 0xff);
4182
               *(row + 1) = (png_byte)(v & 0xff);
4183
            }
4184
4185
            return;
4186
         }
4187
      }
4188
   }
4189
4190
   /* Only get to here if called with a weird row_info; no harm has been done,
4191
    * so just issue a warning.
4192
    */
4193
   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4194
}
4195
#endif
4196
4197
#ifdef PNG_READ_EXPAND_SUPPORTED
4198
/* Expands a palette row to an RGB or RGBA row depending
4199
 * upon whether you supply trans and num_trans.
4200
 */
4201
static void
4202
png_do_expand_palette(png_row_infop row_info, png_bytep row,
4203
    png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
4204
0
{
4205
0
   int shift, value;
4206
0
   png_bytep sp, dp;
4207
0
   png_uint_32 i;
4208
0
   png_uint_32 row_width=row_info->width;
4209
0
4210
0
   png_debug(1, "in png_do_expand_palette");
4211
0
4212
0
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4213
0
   {
4214
0
      if (row_info->bit_depth < 8)
4215
0
      {
4216
0
         switch (row_info->bit_depth)
4217
0
         {
4218
0
            case 1:
4219
0
            {
4220
0
               sp = row + (size_t)((row_width - 1) >> 3);
4221
0
               dp = row + (size_t)row_width - 1;
4222
0
               shift = 7 - (int)((row_width + 7) & 0x07);
4223
0
               for (i = 0; i < row_width; i++)
4224
0
               {
4225
0
                  if ((*sp >> shift) & 0x01)
4226
0
                     *dp = 1;
4227
0
4228
0
                  else
4229
0
                     *dp = 0;
4230
0
4231
0
                  if (shift == 7)
4232
0
                  {
4233
0
                     shift = 0;
4234
0
                     sp--;
4235
0
                  }
4236
0
4237
0
                  else
4238
0
                     shift++;
4239
0
4240
0
                  dp--;
4241
0
               }
4242
0
               break;
4243
0
            }
4244
0
4245
0
            case 2:
4246
0
            {
4247
0
               sp = row + (size_t)((row_width - 1) >> 2);
4248
0
               dp = row + (size_t)row_width - 1;
4249
0
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4250
0
               for (i = 0; i < row_width; i++)
4251
0
               {
4252
0
                  value = (*sp >> shift) & 0x03;
4253
0
                  *dp = (png_byte)value;
4254
0
                  if (shift == 6)
4255
0
                  {
4256
0
                     shift = 0;
4257
0
                     sp--;
4258
0
                  }
4259
0
4260
0
                  else
4261
0
                     shift += 2;
4262
0
4263
0
                  dp--;
4264
0
               }
4265
0
               break;
4266
0
            }
4267
0
4268
0
            case 4:
4269
0
            {
4270
0
               sp = row + (size_t)((row_width - 1) >> 1);
4271
0
               dp = row + (size_t)row_width - 1;
4272
0
               shift = (int)((row_width & 0x01) << 2);
4273
0
               for (i = 0; i < row_width; i++)
4274
0
               {
4275
0
                  value = (*sp >> shift) & 0x0f;
4276
0
                  *dp = (png_byte)value;
4277
0
                  if (shift == 4)
4278
0
                  {
4279
0
                     shift = 0;
4280
0
                     sp--;
4281
0
                  }
4282
0
4283
0
                  else
4284
0
                     shift += 4;
4285
0
4286
0
                  dp--;
4287
0
               }
4288
0
               break;
4289
0
            }
4290
0
4291
0
            default:
4292
0
               break;
4293
0
         }
4294
0
         row_info->bit_depth = 8;
4295
0
         row_info->pixel_depth = 8;
4296
0
         row_info->rowbytes = row_width;
4297
0
      }
4298
0
4299
0
      if (row_info->bit_depth == 8)
4300
0
      {
4301
0
         {
4302
0
            if (num_trans > 0)
4303
0
            {
4304
0
               sp = row + (size_t)row_width - 1;
4305
0
               dp = row + ((size_t)row_width << 2) - 1;
4306
0
4307
0
               for (i = 0; i < row_width; i++)
4308
0
               {
4309
0
                  if ((int)(*sp) >= num_trans)
4310
0
                     *dp-- = 0xff;
4311
0
4312
0
                  else
4313
0
                     *dp-- = trans_alpha[*sp];
4314
0
4315
0
                  *dp-- = palette[*sp].blue;
4316
0
                  *dp-- = palette[*sp].green;
4317
0
                  *dp-- = palette[*sp].red;
4318
0
                  sp--;
4319
0
               }
4320
0
               row_info->bit_depth = 8;
4321
0
               row_info->pixel_depth = 32;
4322
0
               row_info->rowbytes = row_width * 4;
4323
0
               row_info->color_type = 6;
4324
0
               row_info->channels = 4;
4325
0
            }
4326
0
4327
0
            else
4328
0
            {
4329
0
               sp = row + (size_t)row_width - 1;
4330
0
               dp = row + (size_t)(row_width * 3) - 1;
4331
0
4332
0
               for (i = 0; i < row_width; i++)
4333
0
               {
4334
0
                  *dp-- = palette[*sp].blue;
4335
0
                  *dp-- = palette[*sp].green;
4336
0
                  *dp-- = palette[*sp].red;
4337
0
                  sp--;
4338
0
               }
4339
0
4340
0
               row_info->bit_depth = 8;
4341
0
               row_info->pixel_depth = 24;
4342
0
               row_info->rowbytes = row_width * 3;
4343
0
               row_info->color_type = 2;
4344
0
               row_info->channels = 3;
4345
0
            }
4346
0
         }
4347
0
      }
4348
0
   }
4349
0
}
4350
4351
/* If the bit depth < 8, it is expanded to 8.  Also, if the already
4352
 * expanded transparency value is supplied, an alpha channel is built.
4353
 */
4354
static void
4355
png_do_expand(png_row_infop row_info, png_bytep row,
4356
    png_const_color_16p trans_color)
4357
0
{
4358
0
   int shift, value;
4359
0
   png_bytep sp, dp;
4360
0
   png_uint_32 i;
4361
0
   png_uint_32 row_width=row_info->width;
4362
0
4363
0
   png_debug(1, "in png_do_expand");
4364
0
4365
0
   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
4366
0
   {
4367
0
      unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
4368
0
4369
0
      if (row_info->bit_depth < 8)
4370
0
      {
4371
0
         switch (row_info->bit_depth)
4372
0
         {
4373
0
            case 1:
4374
0
            {
4375
0
               gray = (gray & 0x01) * 0xff;
4376
0
               sp = row + (size_t)((row_width - 1) >> 3);
4377
0
               dp = row + (size_t)row_width - 1;
4378
0
               shift = 7 - (int)((row_width + 7) & 0x07);
4379
0
               for (i = 0; i < row_width; i++)
4380
0
               {
4381
0
                  if ((*sp >> shift) & 0x01)
4382
0
                     *dp = 0xff;
4383
0
4384
0
                  else
4385
0
                     *dp = 0;
4386
0
4387
0
                  if (shift == 7)
4388
0
                  {
4389
0
                     shift = 0;
4390
0
                     sp--;
4391
0
                  }
4392
0
4393
0
                  else
4394
0
                     shift++;
4395
0
4396
0
                  dp--;
4397
0
               }
4398
0
               break;
4399
0
            }
4400
0
4401
0
            case 2:
4402
0
            {
4403
0
               gray = (gray & 0x03) * 0x55;
4404
0
               sp = row + (size_t)((row_width - 1) >> 2);
4405
0
               dp = row + (size_t)row_width - 1;
4406
0
               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4407
0
               for (i = 0; i < row_width; i++)
4408
0
               {
4409
0
                  value = (*sp >> shift) & 0x03;
4410
0
                  *dp = (png_byte)(value | (value << 2) | (value << 4) |
4411
0
                     (value << 6));
4412
0
                  if (shift == 6)
4413
0
                  {
4414
0
                     shift = 0;
4415
0
                     sp--;
4416
0
                  }
4417
0
4418
0
                  else
4419
0
                     shift += 2;
4420
0
4421
0
                  dp--;
4422
0
               }
4423
0
               break;
4424
0
            }
4425
0
4426
0
            case 4:
4427
0
            {
4428
0
               gray = (gray & 0x0f) * 0x11;
4429
0
               sp = row + (size_t)((row_width - 1) >> 1);
4430
0
               dp = row + (size_t)row_width - 1;
4431
0
               shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4432
0
               for (i = 0; i < row_width; i++)
4433
0
               {
4434
0
                  value = (*sp >> shift) & 0x0f;
4435
0
                  *dp = (png_byte)(value | (value << 4));
4436
0
                  if (shift == 4)
4437
0
                  {
4438
0
                     shift = 0;
4439
0
                     sp--;
4440
0
                  }
4441
0
4442
0
                  else
4443
0
                     shift = 4;
4444
0
4445
0
                  dp--;
4446
0
               }
4447
0
               break;
4448
0
            }
4449
0
4450
0
            default:
4451
0
               break;
4452
0
         }
4453
0
4454
0
         row_info->bit_depth = 8;
4455
0
         row_info->pixel_depth = 8;
4456
0
         row_info->rowbytes = row_width;
4457
0
      }
4458
0
4459
0
      if (trans_color != NULL)
4460
0
      {
4461
0
         if (row_info->bit_depth == 8)
4462
0
         {
4463
0
            gray = gray & 0xff;
4464
0
            sp = row + (size_t)row_width - 1;
4465
0
            dp = row + ((size_t)row_width << 1) - 1;
4466
0
4467
0
            for (i = 0; i < row_width; i++)
4468
0
            {
4469
0
               if ((*sp & 0xffU) == gray)
4470
0
                  *dp-- = 0;
4471
0
4472
0
               else
4473
0
                  *dp-- = 0xff;
4474
0
4475
0
               *dp-- = *sp--;
4476
0
            }
4477
0
         }
4478
0
4479
0
         else if (row_info->bit_depth == 16)
4480
0
         {
4481
0
            unsigned int gray_high = (gray >> 8) & 0xff;
4482
0
            unsigned int gray_low = gray & 0xff;
4483
0
            sp = row + row_info->rowbytes - 1;
4484
0
            dp = row + (row_info->rowbytes << 1) - 1;
4485
0
            for (i = 0; i < row_width; i++)
4486
0
            {
4487
0
               if ((*(sp - 1) & 0xffU) == gray_high &&
4488
0
                   (*(sp) & 0xffU) == gray_low)
4489
0
               {
4490
0
                  *dp-- = 0;
4491
0
                  *dp-- = 0;
4492
0
               }
4493
0
4494
0
               else
4495
0
               {
4496
0
                  *dp-- = 0xff;
4497
0
                  *dp-- = 0xff;
4498
0
               }
4499
0
4500
0
               *dp-- = *sp--;
4501
0
               *dp-- = *sp--;
4502
0
            }
4503
0
         }
4504
0
4505
0
         row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
4506
0
         row_info->channels = 2;
4507
0
         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4508
0
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
4509
0
             row_width);
4510
0
      }
4511
0
   }
4512
0
   else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
4513
0
       trans_color != NULL)
4514
0
   {
4515
0
      if (row_info->bit_depth == 8)
4516
0
      {
4517
0
         png_byte red = (png_byte)(trans_color->red & 0xff);
4518
0
         png_byte green = (png_byte)(trans_color->green & 0xff);
4519
0
         png_byte blue = (png_byte)(trans_color->blue & 0xff);
4520
0
         sp = row + (size_t)row_info->rowbytes - 1;
4521
0
         dp = row + ((size_t)row_width << 2) - 1;
4522
0
         for (i = 0; i < row_width; i++)
4523
0
         {
4524
0
            if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
4525
0
               *dp-- = 0;
4526
0
4527
0
            else
4528
0
               *dp-- = 0xff;
4529
0
4530
0
            *dp-- = *sp--;
4531
0
            *dp-- = *sp--;
4532
0
            *dp-- = *sp--;
4533
0
         }
4534
0
      }
4535
0
      else if (row_info->bit_depth == 16)
4536
0
      {
4537
0
         png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
4538
0
         png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
4539
0
         png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
4540
0
         png_byte red_low = (png_byte)(trans_color->red & 0xff);
4541
0
         png_byte green_low = (png_byte)(trans_color->green & 0xff);
4542
0
         png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
4543
0
         sp = row + row_info->rowbytes - 1;
4544
0
         dp = row + ((size_t)row_width << 3) - 1;
4545
0
         for (i = 0; i < row_width; i++)
4546
0
         {
4547
0
            if (*(sp - 5) == red_high &&
4548
0
                *(sp - 4) == red_low &&
4549
0
                *(sp - 3) == green_high &&
4550
0
                *(sp - 2) == green_low &&
4551
0
                *(sp - 1) == blue_high &&
4552
0
                *(sp    ) == blue_low)
4553
0
            {
4554
0
               *dp-- = 0;
4555
0
               *dp-- = 0;
4556
0
            }
4557
0
4558
0
            else
4559
0
            {
4560
0
               *dp-- = 0xff;
4561
0
               *dp-- = 0xff;
4562
0
            }
4563
0
4564
0
            *dp-- = *sp--;
4565
0
            *dp-- = *sp--;
4566
0
            *dp-- = *sp--;
4567
0
            *dp-- = *sp--;
4568
0
            *dp-- = *sp--;
4569
0
            *dp-- = *sp--;
4570
0
         }
4571
0
      }
4572
0
      row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
4573
0
      row_info->channels = 4;
4574
0
      row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4575
0
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4576
0
   }
4577
0
}
4578
#endif
4579
4580
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4581
/* If the bit depth is 8 and the color type is not a palette type expand the
4582
 * whole row to 16 bits.  Has no effect otherwise.
4583
 */
4584
static void
4585
png_do_expand_16(png_row_infop row_info, png_bytep row)
4586
{
4587
   if (row_info->bit_depth == 8 &&
4588
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
4589
   {
4590
      /* The row have a sequence of bytes containing [0..255] and we need
4591
       * to turn it into another row containing [0..65535], to do this we
4592
       * calculate:
4593
       *
4594
       *  (input / 255) * 65535
4595
       *
4596
       *  Which happens to be exactly input * 257 and this can be achieved
4597
       *  simply by byte replication in place (copying backwards).
4598
       */
4599
      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
4600
      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
4601
      while (dp > sp)
4602
      {
4603
         dp[-2] = dp[-1] = *--sp; dp -= 2;
4604
      }
4605
4606
      row_info->rowbytes *= 2;
4607
      row_info->bit_depth = 16;
4608
      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4609
   }
4610
}
4611
#endif
4612
4613
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4614
static void
4615
png_do_quantize(png_row_infop row_info, png_bytep row,
4616
    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
4617
{
4618
   png_bytep sp, dp;
4619
   png_uint_32 i;
4620
   png_uint_32 row_width=row_info->width;
4621
4622
   png_debug(1, "in png_do_quantize");
4623
4624
   if (row_info->bit_depth == 8)
4625
   {
4626
      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
4627
      {
4628
         int r, g, b, p;
4629
         sp = row;
4630
         dp = row;
4631
         for (i = 0; i < row_width; i++)
4632
         {
4633
            r = *sp++;
4634
            g = *sp++;
4635
            b = *sp++;
4636
4637
            /* This looks real messy, but the compiler will reduce
4638
             * it down to a reasonable formula.  For example, with
4639
             * 5 bits per color, we get:
4640
             * p = (((r >> 3) & 0x1f) << 10) |
4641
             *    (((g >> 3) & 0x1f) << 5) |
4642
             *    ((b >> 3) & 0x1f);
4643
             */
4644
            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4645
                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4646
                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4647
                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4648
                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4649
                (PNG_QUANTIZE_BLUE_BITS)) |
4650
                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4651
                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4652
4653
            *dp++ = palette_lookup[p];
4654
         }
4655
4656
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4657
         row_info->channels = 1;
4658
         row_info->pixel_depth = row_info->bit_depth;
4659
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4660
      }
4661
4662
      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4663
         palette_lookup != NULL)
4664
      {
4665
         int r, g, b, p;
4666
         sp = row;
4667
         dp = row;
4668
         for (i = 0; i < row_width; i++)
4669
         {
4670
            r = *sp++;
4671
            g = *sp++;
4672
            b = *sp++;
4673
            sp++;
4674
4675
            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4676
                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4677
                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4678
                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4679
                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4680
                (PNG_QUANTIZE_BLUE_BITS)) |
4681
                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4682
                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4683
4684
            *dp++ = palette_lookup[p];
4685
         }
4686
4687
         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4688
         row_info->channels = 1;
4689
         row_info->pixel_depth = row_info->bit_depth;
4690
         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4691
      }
4692
4693
      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4694
         quantize_lookup)
4695
      {
4696
         sp = row;
4697
4698
         for (i = 0; i < row_width; i++, sp++)
4699
         {
4700
            *sp = quantize_lookup[*sp];
4701
         }
4702
      }
4703
   }
4704
}
4705
#endif /* READ_QUANTIZE */
4706
4707
/* Transform the row.  The order of transformations is significant,
4708
 * and is very touchy.  If you add a transformation, take care to
4709
 * decide how it fits in with the other transformations here.
4710
 */
4711
void /* PRIVATE */
4712
png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
4713
0
{
4714
0
   png_debug(1, "in png_do_read_transformations");
4715
0
4716
0
   if (png_ptr->row_buf == NULL)
4717
0
   {
4718
0
      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
4719
0
       * error is incredibly rare and incredibly easy to debug without this
4720
0
       * information.
4721
0
       */
4722
0
      png_error(png_ptr, "NULL row buffer");
4723
0
   }
4724
0
4725
0
   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
4726
0
    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4727
0
    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
4728
0
    * all transformations, however in practice the ROW_INIT always gets done on
4729
0
    * demand, if necessary.
4730
0
    */
4731
0
   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4732
0
       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4733
0
   {
4734
0
      /* Application has failed to call either png_read_start_image() or
4735
0
       * png_read_update_info() after setting transforms that expand pixels.
4736
0
       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4737
0
       */
4738
0
      png_error(png_ptr, "Uninitialized row");
4739
0
   }
4740
0
4741
0
#ifdef PNG_READ_EXPAND_SUPPORTED
4742
0
   if ((png_ptr->transformations & PNG_EXPAND) != 0)
4743
0
   {
4744
0
      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4745
0
      {
4746
0
         png_do_expand_palette(row_info, png_ptr->row_buf + 1,
4747
0
             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4748
0
      }
4749
0
4750
0
      else
4751
0
      {
4752
0
         if (png_ptr->num_trans != 0 &&
4753
0
             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4754
0
            png_do_expand(row_info, png_ptr->row_buf + 1,
4755
0
                &(png_ptr->trans_color));
4756
0
4757
0
         else
4758
0
            png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
4759
0
      }
4760
0
   }
4761
0
#endif
4762
0
4763
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4764
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4765
       (png_ptr->transformations & PNG_COMPOSE) == 0 &&
4766
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4767
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4768
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4769
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4770
#endif
4771
4772
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4773
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4774
   {
4775
      int rgb_error =
4776
          png_do_rgb_to_gray(png_ptr, row_info,
4777
              png_ptr->row_buf + 1);
4778
4779
      if (rgb_error != 0)
4780
      {
4781
         png_ptr->rgb_to_gray_status=1;
4782
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4783
             PNG_RGB_TO_GRAY_WARN)
4784
            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4785
4786
         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4787
             PNG_RGB_TO_GRAY_ERR)
4788
            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4789
      }
4790
   }
4791
#endif
4792
4793
0
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
4794
0
 *
4795
0
 *   In most cases, the "simple transparency" should be done prior to doing
4796
0
 *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
4797
0
 *   pixel is transparent.  You would also need to make sure that the
4798
0
 *   transparency information is upgraded to RGB.
4799
0
 *
4800
0
 *   To summarize, the current flow is:
4801
0
 *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
4802
0
 *                                   with background "in place" if transparent,
4803
0
 *                                   convert to RGB if necessary
4804
0
 *   - Gray + alpha -> composite with gray background and remove alpha bytes,
4805
0
 *                                   convert to RGB if necessary
4806
0
 *
4807
0
 *   To support RGB backgrounds for gray images we need:
4808
0
 *   - Gray + simple transparency -> convert to RGB + simple transparency,
4809
0
 *                                   compare 3 or 6 bytes and composite with
4810
0
 *                                   background "in place" if transparent
4811
0
 *                                   (3x compare/pixel compared to doing
4812
0
 *                                   composite with gray bkgrnd)
4813
0
 *   - Gray + alpha -> convert to RGB + alpha, composite with background and
4814
0
 *                                   remove alpha bytes (3x float
4815
0
 *                                   operations/pixel compared with composite
4816
0
 *                                   on gray background)
4817
0
 *
4818
0
 *  Greg's change will do this.  The reason it wasn't done before is for
4819
0
 *  performance, as this increases the per-pixel operations.  If we would check
4820
0
 *  in advance if the background was gray or RGB, and position the gray-to-RGB
4821
0
 *  transform appropriately, then it would save a lot of work/time.
4822
0
 */
4823
0
4824
0
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4825
0
   /* If gray -> RGB, do so now only if background is non-gray; else do later
4826
0
    * for performance reasons
4827
0
    */
4828
0
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
4829
0
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4830
0
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4831
0
#endif
4832
0
4833
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4834
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4835
   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4836
      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
4837
#endif
4838
4839
0
#ifdef PNG_READ_GAMMA_SUPPORTED
4840
0
   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4841
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4842
      /* Because RGB_TO_GRAY does the gamma transform. */
4843
      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4844
#endif
4845
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4846
   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4847
      /* Because PNG_COMPOSE does the gamma transform if there is something to
4848
       * do (if there is an alpha channel or transparency.)
4849
       */
4850
       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4851
       ((png_ptr->num_trans != 0) ||
4852
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4853
#endif
4854
      /* Because png_init_read_transformations transforms the palette, unless
4855
0
       * RGB_TO_GRAY will do the transform.
4856
0
       */
4857
0
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
4858
0
      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
4859
0
#endif
4860
0
4861
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4862
   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4863
       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
4864
       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4865
       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4866
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4867
          0 /* at_start == false, because SWAP_ALPHA happens later */);
4868
#endif
4869
4870
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4871
   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
4872
       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4873
      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
4874
#endif
4875
4876
0
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4877
0
   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4878
0
      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
4879
0
#endif
4880
0
4881
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
4882
   /* There is no harm in doing both of these because only one has any effect,
4883
    * by putting the 'scale' option first if the app asks for scale (either by
4884
    * calling the API or in a TRANSFORM flag) this is what happens.
4885
    */
4886
   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4887
      png_do_chop(row_info, png_ptr->row_buf + 1);
4888
#endif
4889
4890
#ifdef PNG_READ_QUANTIZE_SUPPORTED
4891
   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4892
   {
4893
      png_do_quantize(row_info, png_ptr->row_buf + 1,
4894
          png_ptr->palette_lookup, png_ptr->quantize_index);
4895
4896
      if (row_info->rowbytes == 0)
4897
         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
4898
   }
4899
#endif /* READ_QUANTIZE */
4900
4901
#ifdef PNG_READ_EXPAND_16_SUPPORTED
4902
   /* Do the expansion now, after all the arithmetic has been done.  Notice
4903
    * that previous transformations can handle the PNG_EXPAND_16 flag if this
4904
    * is efficient (particularly true in the case of gamma correction, where
4905
    * better accuracy results faster!)
4906
    */
4907
   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4908
      png_do_expand_16(row_info, png_ptr->row_buf + 1);
4909
#endif
4910
4911
0
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4912
0
   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4913
0
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
4914
0
       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4915
0
      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4916
0
#endif
4917
0
4918
#ifdef PNG_READ_INVERT_SUPPORTED
4919
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4920
      png_do_invert(row_info, png_ptr->row_buf + 1);
4921
#endif
4922
4923
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4924
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4925
      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
4926
#endif
4927
4928
#ifdef PNG_READ_SHIFT_SUPPORTED
4929
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4930
      png_do_unshift(row_info, png_ptr->row_buf + 1,
4931
          &(png_ptr->shift));
4932
#endif
4933
4934
#ifdef PNG_READ_PACK_SUPPORTED
4935
   if ((png_ptr->transformations & PNG_PACK) != 0)
4936
      png_do_unpack(row_info, png_ptr->row_buf + 1);
4937
#endif
4938
4939
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
4940
   /* Added at libpng-1.5.10 */
4941
   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4942
       png_ptr->num_palette_max >= 0)
4943
      png_do_check_palette_indexes(png_ptr, row_info);
4944
#endif
4945
4946
#ifdef PNG_READ_BGR_SUPPORTED
4947
   if ((png_ptr->transformations & PNG_BGR) != 0)
4948
      png_do_bgr(row_info, png_ptr->row_buf + 1);
4949
#endif
4950
4951
#ifdef PNG_READ_PACKSWAP_SUPPORTED
4952
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4953
      png_do_packswap(row_info, png_ptr->row_buf + 1);
4954
#endif
4955
4956
#ifdef PNG_READ_FILLER_SUPPORTED
4957
   if ((png_ptr->transformations & PNG_FILLER) != 0)
4958
      png_do_read_filler(row_info, png_ptr->row_buf + 1,
4959
          (png_uint_32)png_ptr->filler, png_ptr->flags);
4960
#endif
4961
4962
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
4963
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
4964
      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
4965
#endif
4966
4967
0
#ifdef PNG_READ_16BIT_SUPPORTED
4968
#ifdef PNG_READ_SWAP_SUPPORTED
4969
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4970
      png_do_swap(row_info, png_ptr->row_buf + 1);
4971
#endif
4972
#endif
4973
0
4974
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
4975
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
4976
   {
4977
      if (png_ptr->read_user_transform_fn != NULL)
4978
         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
4979
             (png_ptr,     /* png_ptr */
4980
             row_info,     /* row_info: */
4981
                /*  png_uint_32 width;       width of row */
4982
                /*  size_t rowbytes;         number of bytes in row */
4983
                /*  png_byte color_type;     color type of pixels */
4984
                /*  png_byte bit_depth;      bit depth of samples */
4985
                /*  png_byte channels;       number of channels (1-4) */
4986
                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
4987
             png_ptr->row_buf + 1);    /* start of pixel data for row */
4988
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
4989
      if (png_ptr->user_transform_depth != 0)
4990
         row_info->bit_depth = png_ptr->user_transform_depth;
4991
4992
      if (png_ptr->user_transform_channels != 0)
4993
         row_info->channels = png_ptr->user_transform_channels;
4994
#endif
4995
      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
4996
          row_info->channels);
4997
4998
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
4999
   }
5000
#endif
5001
}
5002
5003
#endif /* READ_TRANSFORMS */
5004
#endif /* READ */