Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpng-1.6.34/pngwtran.c
Line
Count
Source
1
2
/* pngwtran.c - transforms the data in a row for PNG writers
3
 *
4
 * Last changed in libpng 1.6.26 [October 20, 2016]
5
 * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
6
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 */
13
14
#include "pngpriv.h"
15
16
#ifdef PNG_WRITE_SUPPORTED
17
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
18
19
#ifdef PNG_WRITE_PACK_SUPPORTED
20
/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
21
 * row_info bit depth should be 8 (one pixel per byte).  The channels
22
 * should be 1 (this only happens on grayscale and paletted images).
23
 */
24
static void
25
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
26
0
{
27
0
   png_debug(1, "in png_do_pack");
28
29
0
   if (row_info->bit_depth == 8 &&
30
0
      row_info->channels == 1)
31
0
   {
32
0
      switch ((int)bit_depth)
33
0
      {
34
0
         case 1:
35
0
         {
36
0
            png_bytep sp, dp;
37
0
            int mask, v;
38
0
            png_uint_32 i;
39
0
            png_uint_32 row_width = row_info->width;
40
41
0
            sp = row;
42
0
            dp = row;
43
0
            mask = 0x80;
44
0
            v = 0;
45
46
0
            for (i = 0; i < row_width; i++)
47
0
            {
48
0
               if (*sp != 0)
49
0
                  v |= mask;
50
51
0
               sp++;
52
53
0
               if (mask > 1)
54
0
                  mask >>= 1;
55
56
0
               else
57
0
               {
58
0
                  mask = 0x80;
59
0
                  *dp = (png_byte)v;
60
0
                  dp++;
61
0
                  v = 0;
62
0
               }
63
0
            }
64
65
0
            if (mask != 0x80)
66
0
               *dp = (png_byte)v;
67
68
0
            break;
69
0
         }
70
71
0
         case 2:
72
0
         {
73
0
            png_bytep sp, dp;
74
0
            unsigned int shift;
75
0
            int v;
76
0
            png_uint_32 i;
77
0
            png_uint_32 row_width = row_info->width;
78
79
0
            sp = row;
80
0
            dp = row;
81
0
            shift = 6;
82
0
            v = 0;
83
84
0
            for (i = 0; i < row_width; i++)
85
0
            {
86
0
               png_byte value;
87
88
0
               value = (png_byte)(*sp & 0x03);
89
0
               v |= (value << shift);
90
91
0
               if (shift == 0)
92
0
               {
93
0
                  shift = 6;
94
0
                  *dp = (png_byte)v;
95
0
                  dp++;
96
0
                  v = 0;
97
0
               }
98
99
0
               else
100
0
                  shift -= 2;
101
102
0
               sp++;
103
0
            }
104
105
0
            if (shift != 6)
106
0
               *dp = (png_byte)v;
107
108
0
            break;
109
0
         }
110
111
0
         case 4:
112
0
         {
113
0
            png_bytep sp, dp;
114
0
            unsigned int shift;
115
0
            int v;
116
0
            png_uint_32 i;
117
0
            png_uint_32 row_width = row_info->width;
118
119
0
            sp = row;
120
0
            dp = row;
121
0
            shift = 4;
122
0
            v = 0;
123
124
0
            for (i = 0; i < row_width; i++)
125
0
            {
126
0
               png_byte value;
127
128
0
               value = (png_byte)(*sp & 0x0f);
129
0
               v |= (value << shift);
130
131
0
               if (shift == 0)
132
0
               {
133
0
                  shift = 4;
134
0
                  *dp = (png_byte)v;
135
0
                  dp++;
136
0
                  v = 0;
137
0
               }
138
139
0
               else
140
0
                  shift -= 4;
141
142
0
               sp++;
143
0
            }
144
145
0
            if (shift != 4)
146
0
               *dp = (png_byte)v;
147
148
0
            break;
149
0
         }
150
151
0
         default:
152
0
            break;
153
0
      }
154
155
0
      row_info->bit_depth = (png_byte)bit_depth;
156
0
      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
157
0
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
158
0
          row_info->width);
159
0
   }
160
0
}
161
#endif
162
163
#ifdef PNG_WRITE_SHIFT_SUPPORTED
164
/* Shift pixel values to take advantage of whole range.  Pass the
165
 * true number of bits in bit_depth.  The row should be packed
166
 * according to row_info->bit_depth.  Thus, if you had a row of
167
 * bit depth 4, but the pixels only had values from 0 to 7, you
168
 * would pass 3 as bit_depth, and this routine would translate the
169
 * data to 0 to 15.
170
 */
171
static void
172
png_do_shift(png_row_infop row_info, png_bytep row,
173
    png_const_color_8p bit_depth)
174
0
{
175
0
   png_debug(1, "in png_do_shift");
176
177
0
   if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
178
0
   {
179
0
      int shift_start[4], shift_dec[4];
180
0
      unsigned int channels = 0;
181
182
0
      if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
183
0
      {
184
0
         shift_start[channels] = row_info->bit_depth - bit_depth->red;
185
0
         shift_dec[channels] = bit_depth->red;
186
0
         channels++;
187
188
0
         shift_start[channels] = row_info->bit_depth - bit_depth->green;
189
0
         shift_dec[channels] = bit_depth->green;
190
0
         channels++;
191
192
0
         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
193
0
         shift_dec[channels] = bit_depth->blue;
194
0
         channels++;
195
0
      }
196
197
0
      else
198
0
      {
199
0
         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
200
0
         shift_dec[channels] = bit_depth->gray;
201
0
         channels++;
202
0
      }
203
204
0
      if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
205
0
      {
206
0
         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
207
0
         shift_dec[channels] = bit_depth->alpha;
208
0
         channels++;
209
0
      }
210
211
      /* With low row depths, could only be grayscale, so one channel */
212
0
      if (row_info->bit_depth < 8)
213
0
      {
214
0
         png_bytep bp = row;
215
0
         png_size_t i;
216
0
         unsigned int mask;
217
0
         png_size_t row_bytes = row_info->rowbytes;
218
219
0
         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
220
0
            mask = 0x55;
221
222
0
         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
223
0
            mask = 0x11;
224
225
0
         else
226
0
            mask = 0xff;
227
228
0
         for (i = 0; i < row_bytes; i++, bp++)
229
0
         {
230
0
            int j;
231
0
            unsigned int v, out;
232
233
0
            v = *bp;
234
0
            out = 0;
235
236
0
            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
237
0
            {
238
0
               if (j > 0)
239
0
                  out |= v << j;
240
241
0
               else
242
0
                  out |= (v >> (-j)) & mask;
243
0
            }
244
245
0
            *bp = (png_byte)(out & 0xff);
246
0
         }
247
0
      }
248
249
0
      else if (row_info->bit_depth == 8)
250
0
      {
251
0
         png_bytep bp = row;
252
0
         png_uint_32 i;
253
0
         png_uint_32 istop = channels * row_info->width;
254
255
0
         for (i = 0; i < istop; i++, bp++)
256
0
         {
257
258
0
            const unsigned int c = i%channels;
259
0
            int j;
260
0
            unsigned int v, out;
261
262
0
            v = *bp;
263
0
            out = 0;
264
265
0
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
266
0
            {
267
0
               if (j > 0)
268
0
                  out |= v << j;
269
270
0
               else
271
0
                  out |= v >> (-j);
272
0
            }
273
274
0
            *bp = (png_byte)(out & 0xff);
275
0
         }
276
0
      }
277
278
0
      else
279
0
      {
280
0
         png_bytep bp;
281
0
         png_uint_32 i;
282
0
         png_uint_32 istop = channels * row_info->width;
283
284
0
         for (bp = row, i = 0; i < istop; i++)
285
0
         {
286
0
            const unsigned int c = i%channels;
287
0
            int j;
288
0
            unsigned int value, v;
289
290
0
            v = png_get_uint_16(bp);
291
0
            value = 0;
292
293
0
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
294
0
            {
295
0
               if (j > 0)
296
0
                  value |= v << j;
297
298
0
               else
299
0
                  value |= v >> (-j);
300
0
            }
301
0
            *bp++ = (png_byte)((value >> 8) & 0xff);
302
0
            *bp++ = (png_byte)(value & 0xff);
303
0
         }
304
0
      }
305
0
   }
306
0
}
307
#endif
308
309
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
310
static void
311
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
312
0
{
313
0
   png_debug(1, "in png_do_write_swap_alpha");
314
315
0
   {
316
0
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
317
0
      {
318
0
         if (row_info->bit_depth == 8)
319
0
         {
320
            /* This converts from ARGB to RGBA */
321
0
            png_bytep sp, dp;
322
0
            png_uint_32 i;
323
0
            png_uint_32 row_width = row_info->width;
324
325
0
            for (i = 0, sp = dp = row; i < row_width; i++)
326
0
            {
327
0
               png_byte save = *(sp++);
328
0
               *(dp++) = *(sp++);
329
0
               *(dp++) = *(sp++);
330
0
               *(dp++) = *(sp++);
331
0
               *(dp++) = save;
332
0
            }
333
0
         }
334
335
0
#ifdef PNG_WRITE_16BIT_SUPPORTED
336
0
         else
337
0
         {
338
            /* This converts from AARRGGBB to RRGGBBAA */
339
0
            png_bytep sp, dp;
340
0
            png_uint_32 i;
341
0
            png_uint_32 row_width = row_info->width;
342
343
0
            for (i = 0, sp = dp = row; i < row_width; i++)
344
0
            {
345
0
               png_byte save[2];
346
0
               save[0] = *(sp++);
347
0
               save[1] = *(sp++);
348
0
               *(dp++) = *(sp++);
349
0
               *(dp++) = *(sp++);
350
0
               *(dp++) = *(sp++);
351
0
               *(dp++) = *(sp++);
352
0
               *(dp++) = *(sp++);
353
0
               *(dp++) = *(sp++);
354
0
               *(dp++) = save[0];
355
0
               *(dp++) = save[1];
356
0
            }
357
0
         }
358
0
#endif /* WRITE_16BIT */
359
0
      }
360
361
0
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
362
0
      {
363
0
         if (row_info->bit_depth == 8)
364
0
         {
365
            /* This converts from AG to GA */
366
0
            png_bytep sp, dp;
367
0
            png_uint_32 i;
368
0
            png_uint_32 row_width = row_info->width;
369
370
0
            for (i = 0, sp = dp = row; i < row_width; i++)
371
0
            {
372
0
               png_byte save = *(sp++);
373
0
               *(dp++) = *(sp++);
374
0
               *(dp++) = save;
375
0
            }
376
0
         }
377
378
0
#ifdef PNG_WRITE_16BIT_SUPPORTED
379
0
         else
380
0
         {
381
            /* This converts from AAGG to GGAA */
382
0
            png_bytep sp, dp;
383
0
            png_uint_32 i;
384
0
            png_uint_32 row_width = row_info->width;
385
386
0
            for (i = 0, sp = dp = row; i < row_width; i++)
387
0
            {
388
0
               png_byte save[2];
389
0
               save[0] = *(sp++);
390
0
               save[1] = *(sp++);
391
0
               *(dp++) = *(sp++);
392
0
               *(dp++) = *(sp++);
393
0
               *(dp++) = save[0];
394
0
               *(dp++) = save[1];
395
0
            }
396
0
         }
397
0
#endif /* WRITE_16BIT */
398
0
      }
399
0
   }
400
0
}
401
#endif
402
403
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
404
static void
405
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
406
0
{
407
0
   png_debug(1, "in png_do_write_invert_alpha");
408
409
0
   {
410
0
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
411
0
      {
412
0
         if (row_info->bit_depth == 8)
413
0
         {
414
            /* This inverts the alpha channel in RGBA */
415
0
            png_bytep sp, dp;
416
0
            png_uint_32 i;
417
0
            png_uint_32 row_width = row_info->width;
418
419
0
            for (i = 0, sp = dp = row; i < row_width; i++)
420
0
            {
421
               /* Does nothing
422
               *(dp++) = *(sp++);
423
               *(dp++) = *(sp++);
424
               *(dp++) = *(sp++);
425
               */
426
0
               sp+=3; dp = sp;
427
0
               *dp = (png_byte)(255 - *(sp++));
428
0
            }
429
0
         }
430
431
0
#ifdef PNG_WRITE_16BIT_SUPPORTED
432
0
         else
433
0
         {
434
            /* This inverts the alpha channel in RRGGBBAA */
435
0
            png_bytep sp, dp;
436
0
            png_uint_32 i;
437
0
            png_uint_32 row_width = row_info->width;
438
439
0
            for (i = 0, sp = dp = row; i < row_width; i++)
440
0
            {
441
               /* Does nothing
442
               *(dp++) = *(sp++);
443
               *(dp++) = *(sp++);
444
               *(dp++) = *(sp++);
445
               *(dp++) = *(sp++);
446
               *(dp++) = *(sp++);
447
               *(dp++) = *(sp++);
448
               */
449
0
               sp+=6; dp = sp;
450
0
               *(dp++) = (png_byte)(255 - *(sp++));
451
0
               *dp     = (png_byte)(255 - *(sp++));
452
0
            }
453
0
         }
454
0
#endif /* WRITE_16BIT */
455
0
      }
456
457
0
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
458
0
      {
459
0
         if (row_info->bit_depth == 8)
460
0
         {
461
            /* This inverts the alpha channel in GA */
462
0
            png_bytep sp, dp;
463
0
            png_uint_32 i;
464
0
            png_uint_32 row_width = row_info->width;
465
466
0
            for (i = 0, sp = dp = row; i < row_width; i++)
467
0
            {
468
0
               *(dp++) = *(sp++);
469
0
               *(dp++) = (png_byte)(255 - *(sp++));
470
0
            }
471
0
         }
472
473
0
#ifdef PNG_WRITE_16BIT_SUPPORTED
474
0
         else
475
0
         {
476
            /* This inverts the alpha channel in GGAA */
477
0
            png_bytep sp, dp;
478
0
            png_uint_32 i;
479
0
            png_uint_32 row_width = row_info->width;
480
481
0
            for (i = 0, sp = dp = row; i < row_width; i++)
482
0
            {
483
               /* Does nothing
484
               *(dp++) = *(sp++);
485
               *(dp++) = *(sp++);
486
               */
487
0
               sp+=2; dp = sp;
488
0
               *(dp++) = (png_byte)(255 - *(sp++));
489
0
               *dp     = (png_byte)(255 - *(sp++));
490
0
            }
491
0
         }
492
0
#endif /* WRITE_16BIT */
493
0
      }
494
0
   }
495
0
}
496
#endif
497
498
/* Transform the data according to the user's wishes.  The order of
499
 * transformations is significant.
500
 */
501
void /* PRIVATE */
502
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
503
0
{
504
0
   png_debug(1, "in png_do_write_transformations");
505
506
0
   if (png_ptr == NULL)
507
0
      return;
508
509
0
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
510
0
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
511
0
      if (png_ptr->write_user_transform_fn != NULL)
512
0
         (*(png_ptr->write_user_transform_fn)) /* User write transform
513
                                                 function */
514
0
             (png_ptr,  /* png_ptr */
515
0
             row_info,  /* row_info: */
516
                /*  png_uint_32 width;       width of row */
517
                /*  png_size_t rowbytes;     number of bytes in row */
518
                /*  png_byte color_type;     color type of pixels */
519
                /*  png_byte bit_depth;      bit depth of samples */
520
                /*  png_byte channels;       number of channels (1-4) */
521
                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
522
0
             png_ptr->row_buf + 1);      /* start of pixel data for row */
523
0
#endif
524
525
0
#ifdef PNG_WRITE_FILLER_SUPPORTED
526
0
   if ((png_ptr->transformations & PNG_FILLER) != 0)
527
0
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
528
0
          !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
529
0
#endif
530
531
0
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
532
0
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
533
0
      png_do_packswap(row_info, png_ptr->row_buf + 1);
534
0
#endif
535
536
0
#ifdef PNG_WRITE_PACK_SUPPORTED
537
0
   if ((png_ptr->transformations & PNG_PACK) != 0)
538
0
      png_do_pack(row_info, png_ptr->row_buf + 1,
539
0
          (png_uint_32)png_ptr->bit_depth);
540
0
#endif
541
542
0
#ifdef PNG_WRITE_SWAP_SUPPORTED
543
0
#  ifdef PNG_16BIT_SUPPORTED
544
0
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
545
0
      png_do_swap(row_info, png_ptr->row_buf + 1);
546
0
#  endif
547
0
#endif
548
549
0
#ifdef PNG_WRITE_SHIFT_SUPPORTED
550
0
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
551
0
      png_do_shift(row_info, png_ptr->row_buf + 1,
552
0
           &(png_ptr->shift));
553
0
#endif
554
555
0
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
556
0
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
557
0
      png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
558
0
#endif
559
560
0
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
561
0
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
562
0
      png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
563
0
#endif
564
565
0
#ifdef PNG_WRITE_BGR_SUPPORTED
566
0
   if ((png_ptr->transformations & PNG_BGR) != 0)
567
0
      png_do_bgr(row_info, png_ptr->row_buf + 1);
568
0
#endif
569
570
0
#ifdef PNG_WRITE_INVERT_SUPPORTED
571
0
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
572
0
      png_do_invert(row_info, png_ptr->row_buf + 1);
573
0
#endif
574
0
}
575
#endif /* WRITE_TRANSFORMS */
576
#endif /* WRITE */