source: trunk/third/libpng/pngwtran.c @ 18166

Revision 18166, 16.6 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18165, which included commits to RCS files with non-trunk default branches.
Line 
1
2/* pngwtran.c - transforms the data in a row for PNG writers
3 *
4 * libpng 1.2.5 - October 3, 2002
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2002 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 */
10
11#define PNG_INTERNAL
12#include "png.h"
13#ifdef PNG_WRITE_SUPPORTED
14
15/* Transform the data according to the user's wishes.  The order of
16 * transformations is significant.
17 */
18void /* PRIVATE */
19png_do_write_transformations(png_structp png_ptr)
20{
21   png_debug(1, "in png_do_write_transformations\n");
22
23   if (png_ptr == NULL)
24      return;
25
26#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
27   if (png_ptr->transformations & PNG_USER_TRANSFORM)
28      if(png_ptr->write_user_transform_fn != NULL)
29        (*(png_ptr->write_user_transform_fn)) /* user write transform function */
30          (png_ptr,                    /* png_ptr */
31           &(png_ptr->row_info),       /* row_info:     */
32             /*  png_uint_32 width;          width of row */
33             /*  png_uint_32 rowbytes;       number of bytes in row */
34             /*  png_byte color_type;        color type of pixels */
35             /*  png_byte bit_depth;         bit depth of samples */
36             /*  png_byte channels;          number of channels (1-4) */
37             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
38           png_ptr->row_buf + 1);      /* start of pixel data for row */
39#endif
40#if defined(PNG_WRITE_FILLER_SUPPORTED)
41   if (png_ptr->transformations & PNG_FILLER)
42      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
43         png_ptr->flags);
44#endif
45#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
46   if (png_ptr->transformations & PNG_PACKSWAP)
47      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
48#endif
49#if defined(PNG_WRITE_PACK_SUPPORTED)
50   if (png_ptr->transformations & PNG_PACK)
51      png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
52         (png_uint_32)png_ptr->bit_depth);
53#endif
54#if defined(PNG_WRITE_SWAP_SUPPORTED)
55   if (png_ptr->transformations & PNG_SWAP_BYTES)
56      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
57#endif
58#if defined(PNG_WRITE_SHIFT_SUPPORTED)
59   if (png_ptr->transformations & PNG_SHIFT)
60      png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
61         &(png_ptr->shift));
62#endif
63#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
64   if (png_ptr->transformations & PNG_INVERT_ALPHA)
65      png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
66#endif
67#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
68   if (png_ptr->transformations & PNG_SWAP_ALPHA)
69      png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
70#endif
71#if defined(PNG_WRITE_BGR_SUPPORTED)
72   if (png_ptr->transformations & PNG_BGR)
73      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
74#endif
75#if defined(PNG_WRITE_INVERT_SUPPORTED)
76   if (png_ptr->transformations & PNG_INVERT_MONO)
77      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
78#endif
79}
80
81#if defined(PNG_WRITE_PACK_SUPPORTED)
82/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
83 * row_info bit depth should be 8 (one pixel per byte).  The channels
84 * should be 1 (this only happens on grayscale and paletted images).
85 */
86void /* PRIVATE */
87png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
88{
89   png_debug(1, "in png_do_pack\n");
90   if (row_info->bit_depth == 8 &&
91#if defined(PNG_USELESS_TESTS_SUPPORTED)
92       row != NULL && row_info != NULL &&
93#endif
94      row_info->channels == 1)
95   {
96      switch ((int)bit_depth)
97      {
98         case 1:
99         {
100            png_bytep sp, dp;
101            int mask, v;
102            png_uint_32 i;
103            png_uint_32 row_width = row_info->width;
104
105            sp = row;
106            dp = row;
107            mask = 0x80;
108            v = 0;
109
110            for (i = 0; i < row_width; i++)
111            {
112               if (*sp != 0)
113                  v |= mask;
114               sp++;
115               if (mask > 1)
116                  mask >>= 1;
117               else
118               {
119                  mask = 0x80;
120                  *dp = (png_byte)v;
121                  dp++;
122                  v = 0;
123               }
124            }
125            if (mask != 0x80)
126               *dp = (png_byte)v;
127            break;
128         }
129         case 2:
130         {
131            png_bytep sp, dp;
132            int shift, v;
133            png_uint_32 i;
134            png_uint_32 row_width = row_info->width;
135
136            sp = row;
137            dp = row;
138            shift = 6;
139            v = 0;
140            for (i = 0; i < row_width; i++)
141            {
142               png_byte value;
143
144               value = (png_byte)(*sp & 0x03);
145               v |= (value << shift);
146               if (shift == 0)
147               {
148                  shift = 6;
149                  *dp = (png_byte)v;
150                  dp++;
151                  v = 0;
152               }
153               else
154                  shift -= 2;
155               sp++;
156            }
157            if (shift != 6)
158               *dp = (png_byte)v;
159            break;
160         }
161         case 4:
162         {
163            png_bytep sp, dp;
164            int shift, v;
165            png_uint_32 i;
166            png_uint_32 row_width = row_info->width;
167
168            sp = row;
169            dp = row;
170            shift = 4;
171            v = 0;
172            for (i = 0; i < row_width; i++)
173            {
174               png_byte value;
175
176               value = (png_byte)(*sp & 0x0f);
177               v |= (value << shift);
178
179               if (shift == 0)
180               {
181                  shift = 4;
182                  *dp = (png_byte)v;
183                  dp++;
184                  v = 0;
185               }
186               else
187                  shift -= 4;
188
189               sp++;
190            }
191            if (shift != 4)
192               *dp = (png_byte)v;
193            break;
194         }
195      }
196      row_info->bit_depth = (png_byte)bit_depth;
197      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
198      row_info->rowbytes =
199         ((row_info->width * row_info->pixel_depth + 7) >> 3);
200   }
201}
202#endif
203
204#if defined(PNG_WRITE_SHIFT_SUPPORTED)
205/* Shift pixel values to take advantage of whole range.  Pass the
206 * true number of bits in bit_depth.  The row should be packed
207 * according to row_info->bit_depth.  Thus, if you had a row of
208 * bit depth 4, but the pixels only had values from 0 to 7, you
209 * would pass 3 as bit_depth, and this routine would translate the
210 * data to 0 to 15.
211 */
212void /* PRIVATE */
213png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
214{
215   png_debug(1, "in png_do_shift\n");
216#if defined(PNG_USELESS_TESTS_SUPPORTED)
217   if (row != NULL && row_info != NULL &&
218#else
219   if (
220#endif
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#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
336void /* PRIVATE */
337png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
338{
339   png_debug(1, "in png_do_write_swap_alpha\n");
340#if defined(PNG_USELESS_TESTS_SUPPORTED)
341   if (row != NULL && row_info != NULL)
342#endif
343   {
344      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
345      {
346         /* This converts from ARGB to RGBA */
347         if (row_info->bit_depth == 8)
348         {
349            png_bytep sp, dp;
350            png_uint_32 i;
351            png_uint_32 row_width = row_info->width;
352            for (i = 0, sp = dp = row; i < row_width; i++)
353            {
354               png_byte save = *(sp++);
355               *(dp++) = *(sp++);
356               *(dp++) = *(sp++);
357               *(dp++) = *(sp++);
358               *(dp++) = save;
359            }
360         }
361         /* This converts from AARRGGBB to RRGGBBAA */
362         else
363         {
364            png_bytep sp, dp;
365            png_uint_32 i;
366            png_uint_32 row_width = row_info->width;
367
368            for (i = 0, sp = dp = row; i < row_width; i++)
369            {
370               png_byte save[2];
371               save[0] = *(sp++);
372               save[1] = *(sp++);
373               *(dp++) = *(sp++);
374               *(dp++) = *(sp++);
375               *(dp++) = *(sp++);
376               *(dp++) = *(sp++);
377               *(dp++) = *(sp++);
378               *(dp++) = *(sp++);
379               *(dp++) = save[0];
380               *(dp++) = save[1];
381            }
382         }
383      }
384      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
385      {
386         /* This converts from AG to GA */
387         if (row_info->bit_depth == 8)
388         {
389            png_bytep sp, dp;
390            png_uint_32 i;
391            png_uint_32 row_width = row_info->width;
392
393            for (i = 0, sp = dp = row; i < row_width; i++)
394            {
395               png_byte save = *(sp++);
396               *(dp++) = *(sp++);
397               *(dp++) = save;
398            }
399         }
400         /* This converts from AAGG to GGAA */
401         else
402         {
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[2];
410               save[0] = *(sp++);
411               save[1] = *(sp++);
412               *(dp++) = *(sp++);
413               *(dp++) = *(sp++);
414               *(dp++) = save[0];
415               *(dp++) = save[1];
416            }
417         }
418      }
419   }
420}
421#endif
422
423#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
424void /* PRIVATE */
425png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
426{
427   png_debug(1, "in png_do_write_invert_alpha\n");
428#if defined(PNG_USELESS_TESTS_SUPPORTED)
429   if (row != NULL && row_info != NULL)
430#endif
431   {
432      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
433      {
434         /* This inverts the alpha channel in RGBA */
435         if (row_info->bit_depth == 8)
436         {
437            png_bytep sp, dp;
438            png_uint_32 i;
439            png_uint_32 row_width = row_info->width;
440            for (i = 0, sp = dp = row; i < row_width; i++)
441            {
442               *(dp++) = *(sp++);
443               *(dp++) = *(sp++);
444               *(dp++) = *(sp++);
445               *(dp++) = (png_byte)(255 - *(sp++));
446            }
447         }
448         /* This inverts the alpha channel in RRGGBBAA */
449         else
450         {
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               *(dp++) = *(sp++);
458               *(dp++) = *(sp++);
459               *(dp++) = *(sp++);
460               *(dp++) = *(sp++);
461               *(dp++) = *(sp++);
462               *(dp++) = *(sp++);
463               *(dp++) = (png_byte)(255 - *(sp++));
464               *(dp++) = (png_byte)(255 - *(sp++));
465            }
466         }
467      }
468      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
469      {
470         /* This inverts the alpha channel in GA */
471         if (row_info->bit_depth == 8)
472         {
473            png_bytep sp, dp;
474            png_uint_32 i;
475            png_uint_32 row_width = row_info->width;
476
477            for (i = 0, sp = dp = row; i < row_width; i++)
478            {
479               *(dp++) = *(sp++);
480               *(dp++) = (png_byte)(255 - *(sp++));
481            }
482         }
483         /* This inverts the alpha channel in GGAA */
484         else
485         {
486            png_bytep sp, dp;
487            png_uint_32 i;
488            png_uint_32 row_width = row_info->width;
489
490            for (i = 0, sp = dp = row; i < row_width; i++)
491            {
492               *(dp++) = *(sp++);
493               *(dp++) = *(sp++);
494               *(dp++) = (png_byte)(255 - *(sp++));
495               *(dp++) = (png_byte)(255 - *(sp++));
496            }
497         }
498      }
499   }
500}
501#endif
502
503#if defined(PNG_MNG_FEATURES_SUPPORTED)
504/* undoes intrapixel differencing  */
505void /* PRIVATE */
506png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
507{
508   png_debug(1, "in png_do_write_intrapixel\n");
509   if (
510#if defined(PNG_USELESS_TESTS_SUPPORTED)
511       row != NULL && row_info != NULL &&
512#endif
513       (row_info->color_type & PNG_COLOR_MASK_COLOR))
514   {
515      int bytes_per_pixel;
516      png_uint_32 row_width = row_info->width;
517      if (row_info->bit_depth == 8)
518      {
519         png_bytep rp;
520         png_uint_32 i;
521
522         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
523            bytes_per_pixel = 3;
524         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
525            bytes_per_pixel = 4;
526         else
527            return;
528
529         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
530         {
531            *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
532            *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
533         }
534      }
535      else if (row_info->bit_depth == 16)
536      {
537         png_bytep rp;
538         png_uint_32 i;
539
540         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
541            bytes_per_pixel = 6;
542         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
543            bytes_per_pixel = 8;
544         else
545            return;
546
547         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
548         {
549            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
550            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
551            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
552            png_uint_32 red=(s0-s1)&0xffff;
553            png_uint_32 blue=(s2-s1)&0xffff;
554            *(rp  ) = (png_byte)((red>>8)&0xff);
555            *(rp+1) = (png_byte)(red&0xff);
556            *(rp+4) = (png_byte)((blue>>8)&0xff);
557            *(rp+5) = (png_byte)(blue&0xff);
558         }
559      }
560   }
561}
562#endif /* PNG_MNG_FEATURES_SUPPORTED */
563#endif /* PNG_WRITE_SUPPORTED */
Note: See TracBrowser for help on using the repository browser.