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