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