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