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