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