Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libpng/pngtrans.c
9833 views
1
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
2
*
3
* Copyright (c) 2018-2024 Cosmin Truta
4
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
5
* Copyright (c) 1996-1997 Andreas Dilger
6
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
7
*
8
* This code is released under the libpng license.
9
* For conditions of distribution and use, see the disclaimer
10
* and license in png.h
11
*/
12
13
#include "pngpriv.h"
14
15
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
16
17
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
18
/* Turn on BGR-to-RGB mapping */
19
void PNGAPI
20
png_set_bgr(png_structrp png_ptr)
21
{
22
png_debug(1, "in png_set_bgr");
23
24
if (png_ptr == NULL)
25
return;
26
27
png_ptr->transformations |= PNG_BGR;
28
}
29
#endif
30
31
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
32
/* Turn on 16-bit byte swapping */
33
void PNGAPI
34
png_set_swap(png_structrp png_ptr)
35
{
36
png_debug(1, "in png_set_swap");
37
38
if (png_ptr == NULL)
39
return;
40
41
if (png_ptr->bit_depth == 16)
42
png_ptr->transformations |= PNG_SWAP_BYTES;
43
}
44
#endif
45
46
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
47
/* Turn on pixel packing */
48
void PNGAPI
49
png_set_packing(png_structrp png_ptr)
50
{
51
png_debug(1, "in png_set_packing");
52
53
if (png_ptr == NULL)
54
return;
55
56
if (png_ptr->bit_depth < 8)
57
{
58
png_ptr->transformations |= PNG_PACK;
59
# ifdef PNG_WRITE_SUPPORTED
60
png_ptr->usr_bit_depth = 8;
61
# endif
62
}
63
}
64
#endif
65
66
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
67
/* Turn on packed pixel swapping */
68
void PNGAPI
69
png_set_packswap(png_structrp png_ptr)
70
{
71
png_debug(1, "in png_set_packswap");
72
73
if (png_ptr == NULL)
74
return;
75
76
if (png_ptr->bit_depth < 8)
77
png_ptr->transformations |= PNG_PACKSWAP;
78
}
79
#endif
80
81
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
82
void PNGAPI
83
png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
84
{
85
png_debug(1, "in png_set_shift");
86
87
if (png_ptr == NULL)
88
return;
89
90
png_ptr->transformations |= PNG_SHIFT;
91
png_ptr->shift = *true_bits;
92
}
93
#endif
94
95
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
96
defined(PNG_WRITE_INTERLACING_SUPPORTED)
97
int PNGAPI
98
png_set_interlace_handling(png_structrp png_ptr)
99
{
100
png_debug(1, "in png_set_interlace handling");
101
102
if (png_ptr != 0 && png_ptr->interlaced != 0)
103
{
104
png_ptr->transformations |= PNG_INTERLACE;
105
return 7;
106
}
107
108
return 1;
109
}
110
#endif
111
112
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
113
/* Add a filler byte on read, or remove a filler or alpha byte on write.
114
* The filler type has changed in v0.95 to allow future 2-byte fillers
115
* for 48-bit input data, as well as to avoid problems with some compilers
116
* that don't like bytes as parameters.
117
*/
118
void PNGAPI
119
png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
120
{
121
png_debug(1, "in png_set_filler");
122
123
if (png_ptr == NULL)
124
return;
125
126
/* In libpng 1.6 it is possible to determine whether this is a read or write
127
* operation and therefore to do more checking here for a valid call.
128
*/
129
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
130
{
131
# ifdef PNG_READ_FILLER_SUPPORTED
132
/* On read png_set_filler is always valid, regardless of the base PNG
133
* format, because other transformations can give a format where the
134
* filler code can execute (basically an 8 or 16-bit component RGB or G
135
* format.)
136
*
137
* NOTE: usr_channels is not used by the read code! (This has led to
138
* confusion in the past.) The filler is only used in the read code.
139
*/
140
png_ptr->filler = (png_uint_16)filler;
141
# else
142
png_app_error(png_ptr, "png_set_filler not supported on read");
143
PNG_UNUSED(filler) /* not used in the write case */
144
return;
145
# endif
146
}
147
148
else /* write */
149
{
150
# ifdef PNG_WRITE_FILLER_SUPPORTED
151
/* On write the usr_channels parameter must be set correctly at the
152
* start to record the number of channels in the app-supplied data.
153
*/
154
switch (png_ptr->color_type)
155
{
156
case PNG_COLOR_TYPE_RGB:
157
png_ptr->usr_channels = 4;
158
break;
159
160
case PNG_COLOR_TYPE_GRAY:
161
if (png_ptr->bit_depth >= 8)
162
{
163
png_ptr->usr_channels = 2;
164
break;
165
}
166
167
else
168
{
169
/* There simply isn't any code in libpng to strip out bits
170
* from bytes when the components are less than a byte in
171
* size!
172
*/
173
png_app_error(png_ptr,
174
"png_set_filler is invalid for"
175
" low bit depth gray output");
176
return;
177
}
178
179
default:
180
png_app_error(png_ptr,
181
"png_set_filler: inappropriate color type");
182
return;
183
}
184
# else
185
png_app_error(png_ptr, "png_set_filler not supported on write");
186
return;
187
# endif
188
}
189
190
/* Here on success - libpng supports the operation, set the transformation
191
* and the flag to say where the filler channel is.
192
*/
193
png_ptr->transformations |= PNG_FILLER;
194
195
if (filler_loc == PNG_FILLER_AFTER)
196
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
197
198
else
199
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
200
}
201
202
/* Added to libpng-1.2.7 */
203
void PNGAPI
204
png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
205
{
206
png_debug(1, "in png_set_add_alpha");
207
208
if (png_ptr == NULL)
209
return;
210
211
png_set_filler(png_ptr, filler, filler_loc);
212
/* The above may fail to do anything. */
213
if ((png_ptr->transformations & PNG_FILLER) != 0)
214
png_ptr->transformations |= PNG_ADD_ALPHA;
215
}
216
217
#endif
218
219
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
220
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
221
void PNGAPI
222
png_set_swap_alpha(png_structrp png_ptr)
223
{
224
png_debug(1, "in png_set_swap_alpha");
225
226
if (png_ptr == NULL)
227
return;
228
229
png_ptr->transformations |= PNG_SWAP_ALPHA;
230
}
231
#endif
232
233
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
234
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
235
void PNGAPI
236
png_set_invert_alpha(png_structrp png_ptr)
237
{
238
png_debug(1, "in png_set_invert_alpha");
239
240
if (png_ptr == NULL)
241
return;
242
243
png_ptr->transformations |= PNG_INVERT_ALPHA;
244
}
245
#endif
246
247
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
248
void PNGAPI
249
png_set_invert_mono(png_structrp png_ptr)
250
{
251
png_debug(1, "in png_set_invert_mono");
252
253
if (png_ptr == NULL)
254
return;
255
256
png_ptr->transformations |= PNG_INVERT_MONO;
257
}
258
259
/* Invert monochrome grayscale data */
260
void /* PRIVATE */
261
png_do_invert(png_row_infop row_info, png_bytep row)
262
{
263
png_debug(1, "in png_do_invert");
264
265
/* This test removed from libpng version 1.0.13 and 1.2.0:
266
* if (row_info->bit_depth == 1 &&
267
*/
268
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
269
{
270
png_bytep rp = row;
271
size_t i;
272
size_t istop = row_info->rowbytes;
273
274
for (i = 0; i < istop; i++)
275
{
276
*rp = (png_byte)(~(*rp));
277
rp++;
278
}
279
}
280
281
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
282
row_info->bit_depth == 8)
283
{
284
png_bytep rp = row;
285
size_t i;
286
size_t istop = row_info->rowbytes;
287
288
for (i = 0; i < istop; i += 2)
289
{
290
*rp = (png_byte)(~(*rp));
291
rp += 2;
292
}
293
}
294
295
#ifdef PNG_16BIT_SUPPORTED
296
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
297
row_info->bit_depth == 16)
298
{
299
png_bytep rp = row;
300
size_t i;
301
size_t istop = row_info->rowbytes;
302
303
for (i = 0; i < istop; i += 4)
304
{
305
*rp = (png_byte)(~(*rp));
306
*(rp + 1) = (png_byte)(~(*(rp + 1)));
307
rp += 4;
308
}
309
}
310
#endif
311
}
312
#endif
313
314
#ifdef PNG_16BIT_SUPPORTED
315
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
316
/* Swaps byte order on 16-bit depth images */
317
void /* PRIVATE */
318
png_do_swap(png_row_infop row_info, png_bytep row)
319
{
320
png_debug(1, "in png_do_swap");
321
322
if (row_info->bit_depth == 16)
323
{
324
png_bytep rp = row;
325
png_uint_32 i;
326
png_uint_32 istop= row_info->width * row_info->channels;
327
328
for (i = 0; i < istop; i++, rp += 2)
329
{
330
#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
331
/* Feature added to libpng-1.6.11 for testing purposes, not
332
* enabled by default.
333
*/
334
*(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
335
#else
336
png_byte t = *rp;
337
*rp = *(rp + 1);
338
*(rp + 1) = t;
339
#endif
340
}
341
}
342
}
343
#endif
344
#endif
345
346
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
347
static const png_byte onebppswaptable[256] = {
348
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
349
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
350
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
351
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
352
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
353
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
354
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
355
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
356
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
357
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
358
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
359
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
360
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
361
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
362
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
363
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
364
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
365
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
366
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
367
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
368
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
369
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
370
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
371
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
372
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
373
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
374
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
375
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
376
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
377
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
378
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
379
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
380
};
381
382
static const png_byte twobppswaptable[256] = {
383
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
384
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
385
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
386
0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
387
0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
388
0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
389
0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
390
0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
391
0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
392
0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
393
0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
394
0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
395
0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
396
0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
397
0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
398
0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
399
0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
400
0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
401
0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
402
0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
403
0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
404
0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
405
0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
406
0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
407
0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
408
0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
409
0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
410
0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
411
0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
412
0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
413
0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
414
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
415
};
416
417
static const png_byte fourbppswaptable[256] = {
418
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
419
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
420
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
421
0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
422
0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
423
0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
424
0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
425
0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
426
0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
427
0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
428
0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
429
0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
430
0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
431
0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
432
0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
433
0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
434
0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
435
0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
436
0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
437
0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
438
0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
439
0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
440
0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
441
0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
442
0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
443
0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
444
0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
445
0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
446
0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
447
0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
448
0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
449
0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
450
};
451
452
/* Swaps pixel packing order within bytes */
453
void /* PRIVATE */
454
png_do_packswap(png_row_infop row_info, png_bytep row)
455
{
456
png_debug(1, "in png_do_packswap");
457
458
if (row_info->bit_depth < 8)
459
{
460
png_bytep rp;
461
png_const_bytep end, table;
462
463
end = row + row_info->rowbytes;
464
465
if (row_info->bit_depth == 1)
466
table = onebppswaptable;
467
468
else if (row_info->bit_depth == 2)
469
table = twobppswaptable;
470
471
else if (row_info->bit_depth == 4)
472
table = fourbppswaptable;
473
474
else
475
return;
476
477
for (rp = row; rp < end; rp++)
478
*rp = table[*rp];
479
}
480
}
481
#endif /* PACKSWAP || WRITE_PACKSWAP */
482
483
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
484
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
485
/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
486
* somewhat weird combination of flags to determine what to do. All the calls
487
* to png_do_strip_filler are changed in 1.5.2 to call this instead with the
488
* correct arguments.
489
*
490
* The routine isn't general - the channel must be the channel at the start or
491
* end (not in the middle) of each pixel.
492
*/
493
void /* PRIVATE */
494
png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
495
{
496
png_bytep sp = row; /* source pointer */
497
png_bytep dp = row; /* destination pointer */
498
png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
499
500
png_debug(1, "in png_do_strip_channel");
501
502
/* At the start sp will point to the first byte to copy and dp to where
503
* it is copied to. ep always points just beyond the end of the row, so
504
* the loop simply copies (channels-1) channels until sp reaches ep.
505
*
506
* at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
507
* nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
508
*/
509
510
/* GA, GX, XG cases */
511
if (row_info->channels == 2)
512
{
513
if (row_info->bit_depth == 8)
514
{
515
if (at_start != 0) /* Skip initial filler */
516
++sp;
517
else /* Skip initial channel and, for sp, the filler */
518
{
519
sp += 2; ++dp;
520
}
521
522
/* For a 1 pixel wide image there is nothing to do */
523
while (sp < ep)
524
{
525
*dp++ = *sp; sp += 2;
526
}
527
528
row_info->pixel_depth = 8;
529
}
530
531
else if (row_info->bit_depth == 16)
532
{
533
if (at_start != 0) /* Skip initial filler */
534
sp += 2;
535
else /* Skip initial channel and, for sp, the filler */
536
{
537
sp += 4; dp += 2;
538
}
539
540
while (sp < ep)
541
{
542
*dp++ = *sp++; *dp++ = *sp; sp += 3;
543
}
544
545
row_info->pixel_depth = 16;
546
}
547
548
else
549
return; /* bad bit depth */
550
551
row_info->channels = 1;
552
553
/* Finally fix the color type if it records an alpha channel */
554
if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
555
row_info->color_type = PNG_COLOR_TYPE_GRAY;
556
}
557
558
/* RGBA, RGBX, XRGB cases */
559
else if (row_info->channels == 4)
560
{
561
if (row_info->bit_depth == 8)
562
{
563
if (at_start != 0) /* Skip initial filler */
564
++sp;
565
else /* Skip initial channels and, for sp, the filler */
566
{
567
sp += 4; dp += 3;
568
}
569
570
/* Note that the loop adds 3 to dp and 4 to sp each time. */
571
while (sp < ep)
572
{
573
*dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2;
574
}
575
576
row_info->pixel_depth = 24;
577
}
578
579
else if (row_info->bit_depth == 16)
580
{
581
if (at_start != 0) /* Skip initial filler */
582
sp += 2;
583
else /* Skip initial channels and, for sp, the filler */
584
{
585
sp += 8; dp += 6;
586
}
587
588
while (sp < ep)
589
{
590
/* Copy 6 bytes, skip 2 */
591
*dp++ = *sp++; *dp++ = *sp++;
592
*dp++ = *sp++; *dp++ = *sp++;
593
*dp++ = *sp++; *dp++ = *sp; sp += 3;
594
}
595
596
row_info->pixel_depth = 48;
597
}
598
599
else
600
return; /* bad bit depth */
601
602
row_info->channels = 3;
603
604
/* Finally fix the color type if it records an alpha channel */
605
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
606
row_info->color_type = PNG_COLOR_TYPE_RGB;
607
}
608
609
else
610
return; /* The filler channel has gone already */
611
612
/* Fix the rowbytes value. */
613
row_info->rowbytes = (size_t)(dp-row);
614
}
615
#endif
616
617
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
618
/* Swaps red and blue bytes within a pixel */
619
void /* PRIVATE */
620
png_do_bgr(png_row_infop row_info, png_bytep row)
621
{
622
png_debug(1, "in png_do_bgr");
623
624
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
625
{
626
png_uint_32 row_width = row_info->width;
627
if (row_info->bit_depth == 8)
628
{
629
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
630
{
631
png_bytep rp;
632
png_uint_32 i;
633
634
for (i = 0, rp = row; i < row_width; i++, rp += 3)
635
{
636
png_byte save = *rp;
637
*rp = *(rp + 2);
638
*(rp + 2) = save;
639
}
640
}
641
642
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
643
{
644
png_bytep rp;
645
png_uint_32 i;
646
647
for (i = 0, rp = row; i < row_width; i++, rp += 4)
648
{
649
png_byte save = *rp;
650
*rp = *(rp + 2);
651
*(rp + 2) = save;
652
}
653
}
654
}
655
656
#ifdef PNG_16BIT_SUPPORTED
657
else if (row_info->bit_depth == 16)
658
{
659
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
660
{
661
png_bytep rp;
662
png_uint_32 i;
663
664
for (i = 0, rp = row; i < row_width; i++, rp += 6)
665
{
666
png_byte save = *rp;
667
*rp = *(rp + 4);
668
*(rp + 4) = save;
669
save = *(rp + 1);
670
*(rp + 1) = *(rp + 5);
671
*(rp + 5) = save;
672
}
673
}
674
675
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
676
{
677
png_bytep rp;
678
png_uint_32 i;
679
680
for (i = 0, rp = row; i < row_width; i++, rp += 8)
681
{
682
png_byte save = *rp;
683
*rp = *(rp + 4);
684
*(rp + 4) = save;
685
save = *(rp + 1);
686
*(rp + 1) = *(rp + 5);
687
*(rp + 5) = save;
688
}
689
}
690
}
691
#endif
692
}
693
}
694
#endif /* READ_BGR || WRITE_BGR */
695
696
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
697
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
698
/* Added at libpng-1.5.10 */
699
void /* PRIVATE */
700
png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
701
{
702
png_debug(1, "in png_do_check_palette_indexes");
703
704
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
705
png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
706
{
707
/* Calculations moved outside switch in an attempt to stop different
708
* compiler warnings. 'padding' is in *bits* within the last byte, it is
709
* an 'int' because pixel_depth becomes an 'int' in the expression below,
710
* and this calculation is used because it avoids warnings that other
711
* forms produced on either GCC or MSVC.
712
*/
713
int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
714
png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
715
716
switch (row_info->bit_depth)
717
{
718
case 1:
719
{
720
/* in this case, all bytes must be 0 so we don't need
721
* to unpack the pixels except for the rightmost one.
722
*/
723
for (; rp > png_ptr->row_buf; rp--)
724
{
725
if ((*rp >> padding) != 0)
726
png_ptr->num_palette_max = 1;
727
padding = 0;
728
}
729
730
break;
731
}
732
733
case 2:
734
{
735
for (; rp > png_ptr->row_buf; rp--)
736
{
737
int i = ((*rp >> padding) & 0x03);
738
739
if (i > png_ptr->num_palette_max)
740
png_ptr->num_palette_max = i;
741
742
i = (((*rp >> padding) >> 2) & 0x03);
743
744
if (i > png_ptr->num_palette_max)
745
png_ptr->num_palette_max = i;
746
747
i = (((*rp >> padding) >> 4) & 0x03);
748
749
if (i > png_ptr->num_palette_max)
750
png_ptr->num_palette_max = i;
751
752
i = (((*rp >> padding) >> 6) & 0x03);
753
754
if (i > png_ptr->num_palette_max)
755
png_ptr->num_palette_max = i;
756
757
padding = 0;
758
}
759
760
break;
761
}
762
763
case 4:
764
{
765
for (; rp > png_ptr->row_buf; rp--)
766
{
767
int i = ((*rp >> padding) & 0x0f);
768
769
if (i > png_ptr->num_palette_max)
770
png_ptr->num_palette_max = i;
771
772
i = (((*rp >> padding) >> 4) & 0x0f);
773
774
if (i > png_ptr->num_palette_max)
775
png_ptr->num_palette_max = i;
776
777
padding = 0;
778
}
779
780
break;
781
}
782
783
case 8:
784
{
785
for (; rp > png_ptr->row_buf; rp--)
786
{
787
if (*rp > png_ptr->num_palette_max)
788
png_ptr->num_palette_max = (int) *rp;
789
}
790
791
break;
792
}
793
794
default:
795
break;
796
}
797
}
798
}
799
#endif /* CHECK_FOR_INVALID_INDEX */
800
801
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
802
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
803
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
804
void PNGAPI
805
png_set_user_transform_info(png_structrp png_ptr, png_voidp
806
user_transform_ptr, int user_transform_depth, int user_transform_channels)
807
{
808
png_debug(1, "in png_set_user_transform_info");
809
810
if (png_ptr == NULL)
811
return;
812
813
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
814
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
815
(png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
816
{
817
png_app_error(png_ptr,
818
"info change after png_start_read_image or png_read_update_info");
819
return;
820
}
821
#endif
822
823
png_ptr->user_transform_ptr = user_transform_ptr;
824
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
825
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
826
}
827
#endif
828
829
/* This function returns a pointer to the user_transform_ptr associated with
830
* the user transform functions. The application should free any memory
831
* associated with this pointer before png_write_destroy and png_read_destroy
832
* are called.
833
*/
834
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
835
png_voidp PNGAPI
836
png_get_user_transform_ptr(png_const_structrp png_ptr)
837
{
838
if (png_ptr == NULL)
839
return NULL;
840
841
return png_ptr->user_transform_ptr;
842
}
843
#endif
844
845
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
846
png_uint_32 PNGAPI
847
png_get_current_row_number(png_const_structrp png_ptr)
848
{
849
/* See the comments in png.h - this is the sub-image row when reading an
850
* interlaced image.
851
*/
852
if (png_ptr != NULL)
853
return png_ptr->row_number;
854
855
return PNG_UINT_32_MAX; /* help the app not to fail silently */
856
}
857
858
png_byte PNGAPI
859
png_get_current_pass_number(png_const_structrp png_ptr)
860
{
861
if (png_ptr != NULL)
862
return png_ptr->pass;
863
return 8; /* invalid */
864
}
865
#endif /* USER_TRANSFORM_INFO */
866
#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
867
#endif /* READ || WRITE */
868
869