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