fix blinking animation on chromium
[platform/upstream/libpng.git] / pngwtran.c
1
2 /* pngwtran.c - transforms the data in a row for PNG writers
3  *
4  * Copyright (c) 2018 Cosmin Truta
5  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
6  * Copyright (c) 1996-1997 Andreas Dilger
7  * 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 {
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
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       unsigned 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          size_t i;
216          unsigned int mask;
217          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             unsigned int c = i%channels;
258             int j;
259             unsigned int v, out;
260
261             v = *bp;
262             out = 0;
263
264             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
265             {
266                if (j > 0)
267                   out |= v << j;
268
269                else
270                   out |= v >> (-j);
271             }
272
273             *bp = (png_byte)(out & 0xff);
274          }
275       }
276
277       else
278       {
279          png_bytep bp;
280          png_uint_32 i;
281          png_uint_32 istop = channels * row_info->width;
282
283          for (bp = row, i = 0; i < istop; i++)
284          {
285             unsigned int c = i%channels;
286             int j;
287             unsigned int value, v;
288
289             v = png_get_uint_16(bp);
290             value = 0;
291
292             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
293             {
294                if (j > 0)
295                   value |= v << j;
296
297                else
298                   value |= v >> (-j);
299             }
300             *bp++ = (png_byte)((value >> 8) & 0xff);
301             *bp++ = (png_byte)(value & 0xff);
302          }
303       }
304    }
305 }
306 #endif
307
308 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
309 static void
310 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
311 {
312    png_debug(1, "in png_do_write_swap_alpha");
313
314    {
315       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
316       {
317          if (row_info->bit_depth == 8)
318          {
319             /* This converts from ARGB to RGBA */
320             png_bytep sp, dp;
321             png_uint_32 i;
322             png_uint_32 row_width = row_info->width;
323
324             for (i = 0, sp = dp = row; i < row_width; i++)
325             {
326                png_byte save = *(sp++);
327                *(dp++) = *(sp++);
328                *(dp++) = *(sp++);
329                *(dp++) = *(sp++);
330                *(dp++) = save;
331             }
332          }
333
334 #ifdef PNG_WRITE_16BIT_SUPPORTED
335          else
336          {
337             /* This converts from AARRGGBB to RRGGBBAA */
338             png_bytep sp, dp;
339             png_uint_32 i;
340             png_uint_32 row_width = row_info->width;
341
342             for (i = 0, sp = dp = row; i < row_width; i++)
343             {
344                png_byte save[2];
345                save[0] = *(sp++);
346                save[1] = *(sp++);
347                *(dp++) = *(sp++);
348                *(dp++) = *(sp++);
349                *(dp++) = *(sp++);
350                *(dp++) = *(sp++);
351                *(dp++) = *(sp++);
352                *(dp++) = *(sp++);
353                *(dp++) = save[0];
354                *(dp++) = save[1];
355             }
356          }
357 #endif /* WRITE_16BIT */
358       }
359
360       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
361       {
362          if (row_info->bit_depth == 8)
363          {
364             /* This converts from AG to GA */
365             png_bytep sp, dp;
366             png_uint_32 i;
367             png_uint_32 row_width = row_info->width;
368
369             for (i = 0, sp = dp = row; i < row_width; i++)
370             {
371                png_byte save = *(sp++);
372                *(dp++) = *(sp++);
373                *(dp++) = save;
374             }
375          }
376
377 #ifdef PNG_WRITE_16BIT_SUPPORTED
378          else
379          {
380             /* This converts from AAGG to GGAA */
381             png_bytep sp, dp;
382             png_uint_32 i;
383             png_uint_32 row_width = row_info->width;
384
385             for (i = 0, sp = dp = row; i < row_width; i++)
386             {
387                png_byte save[2];
388                save[0] = *(sp++);
389                save[1] = *(sp++);
390                *(dp++) = *(sp++);
391                *(dp++) = *(sp++);
392                *(dp++) = save[0];
393                *(dp++) = save[1];
394             }
395          }
396 #endif /* WRITE_16BIT */
397       }
398    }
399 }
400 #endif
401
402 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
403 static void
404 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
405 {
406    png_debug(1, "in png_do_write_invert_alpha");
407
408    {
409       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
410       {
411          if (row_info->bit_depth == 8)
412          {
413             /* This inverts the alpha channel in RGBA */
414             png_bytep sp, dp;
415             png_uint_32 i;
416             png_uint_32 row_width = row_info->width;
417
418             for (i = 0, sp = dp = row; i < row_width; i++)
419             {
420                /* Does nothing
421                *(dp++) = *(sp++);
422                *(dp++) = *(sp++);
423                *(dp++) = *(sp++);
424                */
425                sp+=3; dp = sp;
426                *dp = (png_byte)(255 - *(sp++));
427             }
428          }
429
430 #ifdef PNG_WRITE_16BIT_SUPPORTED
431          else
432          {
433             /* This inverts the alpha channel in RRGGBBAA */
434             png_bytep sp, dp;
435             png_uint_32 i;
436             png_uint_32 row_width = row_info->width;
437
438             for (i = 0, sp = dp = row; i < row_width; i++)
439             {
440                /* Does nothing
441                *(dp++) = *(sp++);
442                *(dp++) = *(sp++);
443                *(dp++) = *(sp++);
444                *(dp++) = *(sp++);
445                *(dp++) = *(sp++);
446                *(dp++) = *(sp++);
447                */
448                sp+=6; dp = sp;
449                *(dp++) = (png_byte)(255 - *(sp++));
450                *dp     = (png_byte)(255 - *(sp++));
451             }
452          }
453 #endif /* WRITE_16BIT */
454       }
455
456       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
457       {
458          if (row_info->bit_depth == 8)
459          {
460             /* This inverts the alpha channel in GA */
461             png_bytep sp, dp;
462             png_uint_32 i;
463             png_uint_32 row_width = row_info->width;
464
465             for (i = 0, sp = dp = row; i < row_width; i++)
466             {
467                *(dp++) = *(sp++);
468                *(dp++) = (png_byte)(255 - *(sp++));
469             }
470          }
471
472 #ifdef PNG_WRITE_16BIT_SUPPORTED
473          else
474          {
475             /* This inverts the alpha channel in GGAA */
476             png_bytep sp, dp;
477             png_uint_32 i;
478             png_uint_32 row_width = row_info->width;
479
480             for (i = 0, sp = dp = row; i < row_width; i++)
481             {
482                /* Does nothing
483                *(dp++) = *(sp++);
484                *(dp++) = *(sp++);
485                */
486                sp+=2; dp = sp;
487                *(dp++) = (png_byte)(255 - *(sp++));
488                *dp     = (png_byte)(255 - *(sp++));
489             }
490          }
491 #endif /* WRITE_16BIT */
492       }
493    }
494 }
495 #endif
496
497 /* Transform the data according to the user's wishes.  The order of
498  * transformations is significant.
499  */
500 void /* PRIVATE */
501 png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
502 {
503    png_debug(1, "in png_do_write_transformations");
504
505    if (png_ptr == NULL)
506       return;
507
508 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
509    if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
510       if (png_ptr->write_user_transform_fn != NULL)
511          (*(png_ptr->write_user_transform_fn)) /* User write transform
512                                                  function */
513              (png_ptr,  /* png_ptr */
514              row_info,  /* row_info: */
515                 /*  png_uint_32 width;       width of row */
516                 /*  size_t rowbytes;         number of bytes in row */
517                 /*  png_byte color_type;     color type of pixels */
518                 /*  png_byte bit_depth;      bit depth of samples */
519                 /*  png_byte channels;       number of channels (1-4) */
520                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
521              png_ptr->row_buf + 1);      /* start of pixel data for row */
522 #endif
523
524 #ifdef PNG_WRITE_FILLER_SUPPORTED
525    if ((png_ptr->transformations & PNG_FILLER) != 0)
526       png_do_strip_channel(row_info, png_ptr->row_buf + 1,
527           !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
528 #endif
529
530 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
531    if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
532       png_do_packswap(row_info, png_ptr->row_buf + 1);
533 #endif
534
535 #ifdef PNG_WRITE_PACK_SUPPORTED
536    if ((png_ptr->transformations & PNG_PACK) != 0)
537       png_do_pack(row_info, png_ptr->row_buf + 1,
538           (png_uint_32)png_ptr->bit_depth);
539 #endif
540
541 #ifdef PNG_WRITE_SWAP_SUPPORTED
542 #  ifdef PNG_16BIT_SUPPORTED
543    if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
544       png_do_swap(row_info, png_ptr->row_buf + 1);
545 #  endif
546 #endif
547
548 #ifdef PNG_WRITE_SHIFT_SUPPORTED
549    if ((png_ptr->transformations & PNG_SHIFT) != 0)
550       png_do_shift(row_info, png_ptr->row_buf + 1,
551            &(png_ptr->shift));
552 #endif
553
554 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
555    if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
556       png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
557 #endif
558
559 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
560    if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
561       png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
562 #endif
563
564 #ifdef PNG_WRITE_BGR_SUPPORTED
565    if ((png_ptr->transformations & PNG_BGR) != 0)
566       png_do_bgr(row_info, png_ptr->row_buf + 1);
567 #endif
568
569 #ifdef PNG_WRITE_INVERT_SUPPORTED
570    if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
571       png_do_invert(row_info, png_ptr->row_buf + 1);
572 #endif
573 }
574 #endif /* WRITE_TRANSFORMS */
575 #endif /* WRITE */