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