pngcrush  1.8.13
About: Pngcrush is an optimizer for PNG (Portable Network Graphics) files.
  Fossies Dox: pngcrush-1.8.13.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

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