Coverage Report

Created: 2025-11-14 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpng/pngtrans.c
Line
Count
Source
1
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
2
 *
3
 * Copyright (c) 2018-2025 Cosmin Truta
4
 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
5
 * Copyright (c) 1996-1997 Andreas Dilger
6
 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
7
 *
8
 * This code is released under the libpng license.
9
 * For conditions of distribution and use, see the disclaimer
10
 * and license in png.h
11
 */
12
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
20
png_set_bgr(png_struct *png_ptr)
21
0
{
22
0
   png_debug(1, "in png_set_bgr");
23
24
0
   if (png_ptr == NULL)
25
0
      return;
26
27
0
   png_ptr->transformations |= PNG_BGR;
28
0
}
29
#endif
30
31
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
32
/* Turn on 16-bit byte swapping */
33
void
34
png_set_swap(png_struct *png_ptr)
35
0
{
36
0
   png_debug(1, "in png_set_swap");
37
38
0
   if (png_ptr == NULL)
39
0
      return;
40
41
0
   if (png_ptr->bit_depth == 16)
42
0
      png_ptr->transformations |= PNG_SWAP_BYTES;
43
0
}
44
#endif
45
46
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
47
/* Turn on pixel packing */
48
void
49
png_set_packing(png_struct *png_ptr)
50
33.4k
{
51
33.4k
   png_debug(1, "in png_set_packing");
52
53
33.4k
   if (png_ptr == NULL)
54
0
      return;
55
56
33.4k
   if (png_ptr->bit_depth < 8)
57
31.6k
   {
58
31.6k
      png_ptr->transformations |= PNG_PACK;
59
31.6k
#     ifdef PNG_WRITE_SUPPORTED
60
31.6k
         png_ptr->usr_bit_depth = 8;
61
31.6k
#     endif
62
31.6k
   }
63
33.4k
}
64
#endif
65
66
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
67
/* Turn on packed pixel swapping */
68
void
69
png_set_packswap(png_struct *png_ptr)
70
0
{
71
0
   png_debug(1, "in png_set_packswap");
72
73
0
   if (png_ptr == NULL)
74
0
      return;
75
76
0
   if (png_ptr->bit_depth < 8)
77
0
      png_ptr->transformations |= PNG_PACKSWAP;
78
0
}
79
#endif
80
81
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
82
void
83
png_set_shift(png_struct *png_ptr, const png_color_8 *true_bits)
84
0
{
85
0
   png_debug(1, "in png_set_shift");
86
87
0
   if (png_ptr == NULL)
88
0
      return;
89
90
0
   png_ptr->transformations |= PNG_SHIFT;
91
0
   png_ptr->shift = *true_bits;
92
0
}
93
#endif
94
95
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
96
    defined(PNG_WRITE_INTERLACING_SUPPORTED)
97
int
98
png_set_interlace_handling(png_struct *png_ptr)
99
52.7k
{
100
52.7k
   png_debug(1, "in png_set_interlace handling");
101
102
52.7k
   if (png_ptr != 0 && png_ptr->interlaced != 0)
103
27.6k
   {
104
27.6k
      png_ptr->transformations |= PNG_INTERLACE;
105
27.6k
      return 7;
106
27.6k
   }
107
108
25.1k
   return 1;
109
52.7k
}
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
119
png_set_filler(png_struct *png_ptr, png_uint_32 filler, int filler_loc)
120
0
{
121
0
   png_debug(1, "in png_set_filler");
122
123
0
   if (png_ptr == NULL)
124
0
      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
0
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
130
0
   {
131
0
#     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
0
         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
0
   }
147
148
0
   else /* write */
149
0
   {
150
0
#     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
0
         switch (png_ptr->color_type)
155
0
         {
156
0
            case PNG_COLOR_TYPE_RGB:
157
0
               png_ptr->usr_channels = 4;
158
0
               break;
159
160
0
            case PNG_COLOR_TYPE_GRAY:
161
0
               if (png_ptr->bit_depth >= 8)
162
0
               {
163
0
                  png_ptr->usr_channels = 2;
164
0
                  break;
165
0
               }
166
167
0
               else
168
0
               {
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
0
                  png_app_error(png_ptr,
174
0
                      "png_set_filler is invalid for"
175
0
                      " low bit depth gray output");
176
0
                  return;
177
0
               }
178
179
0
            default:
180
0
               png_app_error(png_ptr,
181
0
                   "png_set_filler: inappropriate color type");
182
0
               return;
183
0
         }
184
#     else
185
         png_app_error(png_ptr, "png_set_filler not supported on write");
186
         return;
187
#     endif
188
0
   }
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
0
   png_ptr->transformations |= PNG_FILLER;
194
195
0
   if (filler_loc == PNG_FILLER_AFTER)
196
0
      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
197
198
0
   else
199
0
      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
200
0
}
201
202
/* Added to libpng-1.2.7 */
203
void
204
png_set_add_alpha(png_struct *png_ptr, png_uint_32 filler, int filler_loc)
205
0
{
206
0
   png_debug(1, "in png_set_add_alpha");
207
208
0
   if (png_ptr == NULL)
209
0
      return;
210
211
0
   png_set_filler(png_ptr, filler, filler_loc);
212
   /* The above may fail to do anything. */
213
0
   if ((png_ptr->transformations & PNG_FILLER) != 0)
214
0
      png_ptr->transformations |= PNG_ADD_ALPHA;
215
0
}
216
217
#endif
218
219
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
220
    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
221
void
222
png_set_swap_alpha(png_struct *png_ptr)
223
0
{
224
0
   png_debug(1, "in png_set_swap_alpha");
225
226
0
   if (png_ptr == NULL)
227
0
      return;
228
229
0
   png_ptr->transformations |= PNG_SWAP_ALPHA;
230
0
}
231
#endif
232
233
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
234
    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
235
void
236
png_set_invert_alpha(png_struct *png_ptr)
237
0
{
238
0
   png_debug(1, "in png_set_invert_alpha");
239
240
0
   if (png_ptr == NULL)
241
0
      return;
242
243
0
   png_ptr->transformations |= PNG_INVERT_ALPHA;
244
0
}
245
#endif
246
247
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
248
void
249
png_set_invert_mono(png_struct *png_ptr)
250
0
{
251
0
   png_debug(1, "in png_set_invert_mono");
252
253
0
   if (png_ptr == NULL)
254
0
      return;
255
256
0
   png_ptr->transformations |= PNG_INVERT_MONO;
257
0
}
258
259
/* Invert monochrome grayscale data */
260
void /* PRIVATE */
261
png_do_invert(png_row_info *row_info, png_byte *row)
262
0
{
263
0
   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
0
   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
269
0
   {
270
0
      png_byte *rp = row;
271
0
      size_t i;
272
0
      size_t istop = row_info->rowbytes;
273
274
0
      for (i = 0; i < istop; i++)
275
0
      {
276
0
         *rp = (png_byte)(~(*rp));
277
0
         rp++;
278
0
      }
279
0
   }
280
281
0
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
282
0
      row_info->bit_depth == 8)
283
0
   {
284
0
      png_byte *rp = row;
285
0
      size_t i;
286
0
      size_t istop = row_info->rowbytes;
287
288
0
      for (i = 0; i < istop; i += 2)
289
0
      {
290
0
         *rp = (png_byte)(~(*rp));
291
0
         rp += 2;
292
0
      }
293
0
   }
294
295
0
#ifdef PNG_16BIT_SUPPORTED
296
0
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
297
0
      row_info->bit_depth == 16)
298
0
   {
299
0
      png_byte *rp = row;
300
0
      size_t i;
301
0
      size_t istop = row_info->rowbytes;
302
303
0
      for (i = 0; i < istop; i += 4)
304
0
      {
305
0
         *rp = (png_byte)(~(*rp));
306
0
         *(rp + 1) = (png_byte)(~(*(rp + 1)));
307
0
         rp += 4;
308
0
      }
309
0
   }
310
0
#endif
311
0
}
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_info *row_info, png_byte *row)
319
0
{
320
0
   png_debug(1, "in png_do_swap");
321
322
0
   if (row_info->bit_depth == 16)
323
0
   {
324
0
      png_byte *rp = row;
325
0
      png_uint_32 i;
326
0
      png_uint_32 istop= row_info->width * row_info->channels;
327
328
0
      for (i = 0; i < istop; i++, rp += 2)
329
0
      {
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
0
         png_byte t = *rp;
337
0
         *rp = *(rp + 1);
338
0
         *(rp + 1) = t;
339
0
#endif
340
0
      }
341
0
   }
342
0
}
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_info *row_info, png_byte *row)
455
0
{
456
0
   png_debug(1, "in png_do_packswap");
457
458
0
   if (row_info->bit_depth < 8)
459
0
   {
460
0
      const png_byte *table;
461
0
      png_byte *rp;
462
0
      png_byte *row_end = row + row_info->rowbytes;
463
464
0
      if (row_info->bit_depth == 1)
465
0
         table = onebppswaptable;
466
467
0
      else if (row_info->bit_depth == 2)
468
0
         table = twobppswaptable;
469
470
0
      else if (row_info->bit_depth == 4)
471
0
         table = fourbppswaptable;
472
473
0
      else
474
0
         return;
475
476
0
      for (rp = row; rp < row_end; rp++)
477
0
         *rp = table[*rp];
478
0
   }
479
0
}
480
#endif /* PACKSWAP || WRITE_PACKSWAP */
481
482
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
483
    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
484
/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
485
 * somewhat weird combination of flags to determine what to do.  All the calls
486
 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
487
 * correct arguments.
488
 *
489
 * The routine isn't general - the channel must be the channel at the start or
490
 * end (not in the middle) of each pixel.
491
 */
492
void /* PRIVATE */
493
png_do_strip_channel(png_row_info *row_info, png_byte *row, int at_start)
494
0
{
495
0
   png_byte *sp = row; /* source pointer */
496
0
   png_byte *dp = row; /* destination pointer */
497
0
   png_byte *ep = row + row_info->rowbytes; /* One beyond end of row */
498
499
0
   png_debug(1, "in png_do_strip_channel");
500
501
   /* At the start sp will point to the first byte to copy and dp to where
502
    * it is copied to.  ep always points just beyond the end of the row, so
503
    * the loop simply copies (channels-1) channels until sp reaches ep.
504
    *
505
    * at_start:        0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
506
    *            nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
507
    */
508
509
   /* GA, GX, XG cases */
510
0
   if (row_info->channels == 2)
511
0
   {
512
0
      if (row_info->bit_depth == 8)
513
0
      {
514
0
         if (at_start != 0) /* Skip initial filler */
515
0
            ++sp;
516
0
         else          /* Skip initial channel and, for sp, the filler */
517
0
         {
518
0
            sp += 2; ++dp;
519
0
         }
520
521
         /* For a 1 pixel wide image there is nothing to do */
522
0
         while (sp < ep)
523
0
         {
524
0
            *dp++ = *sp; sp += 2;
525
0
         }
526
527
0
         row_info->pixel_depth = 8;
528
0
      }
529
530
0
      else if (row_info->bit_depth == 16)
531
0
      {
532
0
         if (at_start != 0) /* Skip initial filler */
533
0
            sp += 2;
534
0
         else          /* Skip initial channel and, for sp, the filler */
535
0
         {
536
0
            sp += 4; dp += 2;
537
0
         }
538
539
0
         while (sp < ep)
540
0
         {
541
0
            *dp++ = *sp++; *dp++ = *sp; sp += 3;
542
0
         }
543
544
0
         row_info->pixel_depth = 16;
545
0
      }
546
547
0
      else
548
0
         return; /* bad bit depth */
549
550
0
      row_info->channels = 1;
551
552
      /* Finally fix the color type if it records an alpha channel */
553
0
      if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
554
0
         row_info->color_type = PNG_COLOR_TYPE_GRAY;
555
0
   }
556
557
   /* RGBA, RGBX, XRGB cases */
558
0
   else if (row_info->channels == 4)
559
0
   {
560
0
      if (row_info->bit_depth == 8)
561
0
      {
562
0
         if (at_start != 0) /* Skip initial filler */
563
0
            ++sp;
564
0
         else          /* Skip initial channels and, for sp, the filler */
565
0
         {
566
0
            sp += 4; dp += 3;
567
0
         }
568
569
         /* Note that the loop adds 3 to dp and 4 to sp each time. */
570
0
         while (sp < ep)
571
0
         {
572
0
            *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2;
573
0
         }
574
575
0
         row_info->pixel_depth = 24;
576
0
      }
577
578
0
      else if (row_info->bit_depth == 16)
579
0
      {
580
0
         if (at_start != 0) /* Skip initial filler */
581
0
            sp += 2;
582
0
         else          /* Skip initial channels and, for sp, the filler */
583
0
         {
584
0
            sp += 8; dp += 6;
585
0
         }
586
587
0
         while (sp < ep)
588
0
         {
589
            /* Copy 6 bytes, skip 2 */
590
0
            *dp++ = *sp++; *dp++ = *sp++;
591
0
            *dp++ = *sp++; *dp++ = *sp++;
592
0
            *dp++ = *sp++; *dp++ = *sp; sp += 3;
593
0
         }
594
595
0
         row_info->pixel_depth = 48;
596
0
      }
597
598
0
      else
599
0
         return; /* bad bit depth */
600
601
0
      row_info->channels = 3;
602
603
      /* Finally fix the color type if it records an alpha channel */
604
0
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
605
0
         row_info->color_type = PNG_COLOR_TYPE_RGB;
606
0
   }
607
608
0
   else
609
0
      return; /* The filler channel has gone already */
610
611
   /* Fix the rowbytes value. */
612
0
   row_info->rowbytes = (size_t)(dp-row);
613
0
}
614
#endif
615
616
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
617
/* Swaps red and blue bytes within a pixel */
618
void /* PRIVATE */
619
png_do_bgr(png_row_info *row_info, png_byte *row)
620
0
{
621
0
   png_debug(1, "in png_do_bgr");
622
623
0
   if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
624
0
   {
625
0
      png_uint_32 row_width = row_info->width;
626
0
      if (row_info->bit_depth == 8)
627
0
      {
628
0
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
629
0
         {
630
0
            png_byte *rp;
631
0
            png_uint_32 i;
632
633
0
            for (i = 0, rp = row; i < row_width; i++, rp += 3)
634
0
            {
635
0
               png_byte save = *rp;
636
0
               *rp = *(rp + 2);
637
0
               *(rp + 2) = save;
638
0
            }
639
0
         }
640
641
0
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
642
0
         {
643
0
            png_byte *rp;
644
0
            png_uint_32 i;
645
646
0
            for (i = 0, rp = row; i < row_width; i++, rp += 4)
647
0
            {
648
0
               png_byte save = *rp;
649
0
               *rp = *(rp + 2);
650
0
               *(rp + 2) = save;
651
0
            }
652
0
         }
653
0
      }
654
655
0
#ifdef PNG_16BIT_SUPPORTED
656
0
      else if (row_info->bit_depth == 16)
657
0
      {
658
0
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
659
0
         {
660
0
            png_byte *rp;
661
0
            png_uint_32 i;
662
663
0
            for (i = 0, rp = row; i < row_width; i++, rp += 6)
664
0
            {
665
0
               png_byte save = *rp;
666
0
               *rp = *(rp + 4);
667
0
               *(rp + 4) = save;
668
0
               save = *(rp + 1);
669
0
               *(rp + 1) = *(rp + 5);
670
0
               *(rp + 5) = save;
671
0
            }
672
0
         }
673
674
0
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
675
0
         {
676
0
            png_byte *rp;
677
0
            png_uint_32 i;
678
679
0
            for (i = 0, rp = row; i < row_width; i++, rp += 8)
680
0
            {
681
0
               png_byte save = *rp;
682
0
               *rp = *(rp + 4);
683
0
               *(rp + 4) = save;
684
0
               save = *(rp + 1);
685
0
               *(rp + 1) = *(rp + 5);
686
0
               *(rp + 5) = save;
687
0
            }
688
0
         }
689
0
      }
690
0
#endif
691
0
   }
692
0
}
693
#endif /* READ_BGR || WRITE_BGR */
694
695
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
696
    defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
697
/* Added at libpng-1.5.10 */
698
void /* PRIVATE */
699
png_do_check_palette_indexes(png_struct *png_ptr, png_row_info *row_info)
700
17.3k
{
701
17.3k
   png_debug(1, "in png_do_check_palette_indexes");
702
703
17.3k
   if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
704
15.3k
      png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
705
15.3k
   {
706
      /* Calculations moved outside switch in an attempt to stop different
707
       * compiler warnings.  'padding' is in *bits* within the last byte, it is
708
       * an 'int' because pixel_depth becomes an 'int' in the expression below,
709
       * and this calculation is used because it avoids warnings that other
710
       * forms produced on either GCC or MSVC.
711
       */
712
15.3k
      int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
713
15.3k
      png_byte *rp = png_ptr->row_buf + row_info->rowbytes;
714
715
15.3k
      switch (row_info->bit_depth)
716
15.3k
      {
717
0
         case 1:
718
0
         {
719
            /* in this case, all bytes must be 0 so we don't need
720
             * to unpack the pixels except for the rightmost one.
721
             */
722
0
            for (; rp > png_ptr->row_buf; rp--)
723
0
            {
724
0
              if ((*rp >> padding) != 0)
725
0
                 png_ptr->num_palette_max = 1;
726
0
              padding = 0;
727
0
            }
728
729
0
            break;
730
0
         }
731
732
481
         case 2:
733
481
         {
734
7.98k
            for (; rp > png_ptr->row_buf; rp--)
735
7.50k
            {
736
7.50k
              int i = ((*rp >> padding) & 0x03);
737
738
7.50k
              if (i > png_ptr->num_palette_max)
739
16
                 png_ptr->num_palette_max = i;
740
741
7.50k
              i = (((*rp >> padding) >> 2) & 0x03);
742
743
7.50k
              if (i > png_ptr->num_palette_max)
744
0
                 png_ptr->num_palette_max = i;
745
746
7.50k
              i = (((*rp >> padding) >> 4) & 0x03);
747
748
7.50k
              if (i > png_ptr->num_palette_max)
749
1
                 png_ptr->num_palette_max = i;
750
751
7.50k
              i = (((*rp >> padding) >> 6) & 0x03);
752
753
7.50k
              if (i > png_ptr->num_palette_max)
754
3
                 png_ptr->num_palette_max = i;
755
756
7.50k
              padding = 0;
757
7.50k
            }
758
759
481
            break;
760
0
         }
761
762
1.35k
         case 4:
763
1.35k
         {
764
88.1k
            for (; rp > png_ptr->row_buf; rp--)
765
86.7k
            {
766
86.7k
              int i = ((*rp >> padding) & 0x0f);
767
768
86.7k
              if (i > png_ptr->num_palette_max)
769
64
                 png_ptr->num_palette_max = i;
770
771
86.7k
              i = (((*rp >> padding) >> 4) & 0x0f);
772
773
86.7k
              if (i > png_ptr->num_palette_max)
774
30
                 png_ptr->num_palette_max = i;
775
776
86.7k
              padding = 0;
777
86.7k
            }
778
779
1.35k
            break;
780
0
         }
781
782
13.4k
         case 8:
783
13.4k
         {
784
3.38M
            for (; rp > png_ptr->row_buf; rp--)
785
3.36M
            {
786
3.36M
               if (*rp > png_ptr->num_palette_max)
787
3.35k
                  png_ptr->num_palette_max = (int) *rp;
788
3.36M
            }
789
790
13.4k
            break;
791
0
         }
792
793
0
         default:
794
0
            break;
795
15.3k
      }
796
15.3k
   }
797
17.3k
}
798
#endif /* CHECK_FOR_INVALID_INDEX */
799
800
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
801
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
802
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
803
void
804
png_set_user_transform_info(png_struct *png_ptr, void *user_transform_ptr,
805
    int user_transform_depth, int user_transform_channels)
806
0
{
807
0
   png_debug(1, "in png_set_user_transform_info");
808
809
0
   if (png_ptr == NULL)
810
0
      return;
811
812
0
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
813
0
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
814
0
      (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
815
0
   {
816
0
      png_app_error(png_ptr,
817
0
          "info change after png_start_read_image or png_read_update_info");
818
0
      return;
819
0
   }
820
0
#endif
821
822
0
   png_ptr->user_transform_ptr = user_transform_ptr;
823
0
   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
824
0
   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
825
0
}
826
#endif
827
828
/* This function returns a pointer to the user_transform_ptr associated with
829
 * the user transform functions.  The application should free any memory
830
 * associated with this pointer before png_write_destroy and png_read_destroy
831
 * are called.
832
 */
833
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
834
void *
835
png_get_user_transform_ptr(const png_struct *png_ptr)
836
0
{
837
0
   if (png_ptr == NULL)
838
0
      return NULL;
839
840
0
   return png_ptr->user_transform_ptr;
841
0
}
842
#endif
843
844
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
845
png_uint_32
846
png_get_current_row_number(const png_struct *png_ptr)
847
0
{
848
   /* See the comments in png.h - this is the sub-image row when reading an
849
    * interlaced image.
850
    */
851
0
   if (png_ptr != NULL)
852
0
      return png_ptr->row_number;
853
854
0
   return PNG_UINT_32_MAX; /* help the app not to fail silently */
855
0
}
856
857
png_byte
858
png_get_current_pass_number(const png_struct *png_ptr)
859
0
{
860
0
   if (png_ptr != NULL)
861
0
      return png_ptr->pass;
862
0
   return 8; /* invalid */
863
0
}
864
#endif /* USER_TRANSFORM_INFO */
865
#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
866
#endif /* READ || WRITE */