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