|
1 |
|
2 /* pngwtran.c - transforms the data in a row for PNG writers |
|
3 * |
|
4 * Last changed in libpng 1.2.37 [June 4, 2009] |
|
5 * Copyright (c) 1998-2009 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_INTERNAL |
|
15 #include "png.h" |
|
16 #ifdef PNG_WRITE_SUPPORTED |
|
17 |
|
18 /* Transform the data according to the user's wishes. The order of |
|
19 * transformations is significant. |
|
20 */ |
|
21 void /* PRIVATE */ |
|
22 png_do_write_transformations(png_structp png_ptr) |
|
23 { |
|
24 png_debug(1, "in png_do_write_transformations"); |
|
25 |
|
26 if (png_ptr == NULL) |
|
27 return; |
|
28 |
|
29 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
|
30 if (png_ptr->transformations & PNG_USER_TRANSFORM) |
|
31 if (png_ptr->write_user_transform_fn != NULL) |
|
32 (*(png_ptr->write_user_transform_fn)) /* User write transform function */ |
|
33 (png_ptr, /* png_ptr */ |
|
34 &(png_ptr->row_info), /* row_info: */ |
|
35 /* png_uint_32 width; width of row */ |
|
36 /* png_uint_32 rowbytes; number of bytes in row */ |
|
37 /* png_byte color_type; color type of pixels */ |
|
38 /* png_byte bit_depth; bit depth of samples */ |
|
39 /* png_byte channels; number of channels (1-4) */ |
|
40 /* png_byte pixel_depth; bits per pixel (depth*channels) */ |
|
41 png_ptr->row_buf + 1); /* start of pixel data for row */ |
|
42 #endif |
|
43 #if defined(PNG_WRITE_FILLER_SUPPORTED) |
|
44 if (png_ptr->transformations & PNG_FILLER) |
|
45 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, |
|
46 png_ptr->flags); |
|
47 #endif |
|
48 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) |
|
49 if (png_ptr->transformations & PNG_PACKSWAP) |
|
50 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
51 #endif |
|
52 #if defined(PNG_WRITE_PACK_SUPPORTED) |
|
53 if (png_ptr->transformations & PNG_PACK) |
|
54 png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, |
|
55 (png_uint_32)png_ptr->bit_depth); |
|
56 #endif |
|
57 #if defined(PNG_WRITE_SWAP_SUPPORTED) |
|
58 if (png_ptr->transformations & PNG_SWAP_BYTES) |
|
59 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
60 #endif |
|
61 #if defined(PNG_WRITE_SHIFT_SUPPORTED) |
|
62 if (png_ptr->transformations & PNG_SHIFT) |
|
63 png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, |
|
64 &(png_ptr->shift)); |
|
65 #endif |
|
66 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) |
|
67 if (png_ptr->transformations & PNG_SWAP_ALPHA) |
|
68 png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
69 #endif |
|
70 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) |
|
71 if (png_ptr->transformations & PNG_INVERT_ALPHA) |
|
72 png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
73 #endif |
|
74 #if defined(PNG_WRITE_BGR_SUPPORTED) |
|
75 if (png_ptr->transformations & PNG_BGR) |
|
76 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
77 #endif |
|
78 #if defined(PNG_WRITE_INVERT_SUPPORTED) |
|
79 if (png_ptr->transformations & PNG_INVERT_MONO) |
|
80 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); |
|
81 #endif |
|
82 } |
|
83 |
|
84 #if defined(PNG_WRITE_PACK_SUPPORTED) |
|
85 /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The |
|
86 * row_info bit depth should be 8 (one pixel per byte). The channels |
|
87 * should be 1 (this only happens on grayscale and paletted images). |
|
88 */ |
|
89 void /* PRIVATE */ |
|
90 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) |
|
91 { |
|
92 png_debug(1, "in png_do_pack"); |
|
93 if (row_info->bit_depth == 8 && |
|
94 #if defined(PNG_USELESS_TESTS_SUPPORTED) |
|
95 row != NULL && row_info != NULL && |
|
96 #endif |
|
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 #if defined(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 #if defined(PNG_USELESS_TESTS_SUPPORTED) |
|
220 if (row != NULL && row_info != NULL && |
|
221 #else |
|
222 if ( |
|
223 #endif |
|
224 row_info->color_type != PNG_COLOR_TYPE_PALETTE) |
|
225 { |
|
226 int shift_start[4], shift_dec[4]; |
|
227 int channels = 0; |
|
228 |
|
229 if (row_info->color_type & PNG_COLOR_MASK_COLOR) |
|
230 { |
|
231 shift_start[channels] = row_info->bit_depth - bit_depth->red; |
|
232 shift_dec[channels] = bit_depth->red; |
|
233 channels++; |
|
234 shift_start[channels] = row_info->bit_depth - bit_depth->green; |
|
235 shift_dec[channels] = bit_depth->green; |
|
236 channels++; |
|
237 shift_start[channels] = row_info->bit_depth - bit_depth->blue; |
|
238 shift_dec[channels] = bit_depth->blue; |
|
239 channels++; |
|
240 } |
|
241 else |
|
242 { |
|
243 shift_start[channels] = row_info->bit_depth - bit_depth->gray; |
|
244 shift_dec[channels] = bit_depth->gray; |
|
245 channels++; |
|
246 } |
|
247 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) |
|
248 { |
|
249 shift_start[channels] = row_info->bit_depth - bit_depth->alpha; |
|
250 shift_dec[channels] = bit_depth->alpha; |
|
251 channels++; |
|
252 } |
|
253 |
|
254 /* With low row depths, could only be grayscale, so one channel */ |
|
255 if (row_info->bit_depth < 8) |
|
256 { |
|
257 png_bytep bp = row; |
|
258 png_uint_32 i; |
|
259 png_byte mask; |
|
260 png_uint_32 row_bytes = row_info->rowbytes; |
|
261 |
|
262 if (bit_depth->gray == 1 && row_info->bit_depth == 2) |
|
263 mask = 0x55; |
|
264 else if (row_info->bit_depth == 4 && bit_depth->gray == 3) |
|
265 mask = 0x11; |
|
266 else |
|
267 mask = 0xff; |
|
268 |
|
269 for (i = 0; i < row_bytes; i++, bp++) |
|
270 { |
|
271 png_uint_16 v; |
|
272 int j; |
|
273 |
|
274 v = *bp; |
|
275 *bp = 0; |
|
276 for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) |
|
277 { |
|
278 if (j > 0) |
|
279 *bp |= (png_byte)((v << j) & 0xff); |
|
280 else |
|
281 *bp |= (png_byte)((v >> (-j)) & mask); |
|
282 } |
|
283 } |
|
284 } |
|
285 else if (row_info->bit_depth == 8) |
|
286 { |
|
287 png_bytep bp = row; |
|
288 png_uint_32 i; |
|
289 png_uint_32 istop = channels * row_info->width; |
|
290 |
|
291 for (i = 0; i < istop; i++, bp++) |
|
292 { |
|
293 |
|
294 png_uint_16 v; |
|
295 int j; |
|
296 int c = (int)(i%channels); |
|
297 |
|
298 v = *bp; |
|
299 *bp = 0; |
|
300 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) |
|
301 { |
|
302 if (j > 0) |
|
303 *bp |= (png_byte)((v << j) & 0xff); |
|
304 else |
|
305 *bp |= (png_byte)((v >> (-j)) & 0xff); |
|
306 } |
|
307 } |
|
308 } |
|
309 else |
|
310 { |
|
311 png_bytep bp; |
|
312 png_uint_32 i; |
|
313 png_uint_32 istop = channels * row_info->width; |
|
314 |
|
315 for (bp = row, i = 0; i < istop; i++) |
|
316 { |
|
317 int c = (int)(i%channels); |
|
318 png_uint_16 value, v; |
|
319 int j; |
|
320 |
|
321 v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); |
|
322 value = 0; |
|
323 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) |
|
324 { |
|
325 if (j > 0) |
|
326 value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); |
|
327 else |
|
328 value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); |
|
329 } |
|
330 *bp++ = (png_byte)(value >> 8); |
|
331 *bp++ = (png_byte)(value & 0xff); |
|
332 } |
|
333 } |
|
334 } |
|
335 } |
|
336 #endif |
|
337 |
|
338 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) |
|
339 void /* PRIVATE */ |
|
340 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) |
|
341 { |
|
342 png_debug(1, "in png_do_write_swap_alpha"); |
|
343 #if defined(PNG_USELESS_TESTS_SUPPORTED) |
|
344 if (row != NULL && row_info != NULL) |
|
345 #endif |
|
346 { |
|
347 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
|
348 { |
|
349 /* This converts from ARGB to RGBA */ |
|
350 if (row_info->bit_depth == 8) |
|
351 { |
|
352 png_bytep sp, dp; |
|
353 png_uint_32 i; |
|
354 png_uint_32 row_width = row_info->width; |
|
355 for (i = 0, sp = dp = row; i < row_width; i++) |
|
356 { |
|
357 png_byte save = *(sp++); |
|
358 *(dp++) = *(sp++); |
|
359 *(dp++) = *(sp++); |
|
360 *(dp++) = *(sp++); |
|
361 *(dp++) = save; |
|
362 } |
|
363 } |
|
364 /* This converts from AARRGGBB to RRGGBBAA */ |
|
365 else |
|
366 { |
|
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 } |
|
387 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) |
|
388 { |
|
389 /* This converts from AG to GA */ |
|
390 if (row_info->bit_depth == 8) |
|
391 { |
|
392 png_bytep sp, dp; |
|
393 png_uint_32 i; |
|
394 png_uint_32 row_width = row_info->width; |
|
395 |
|
396 for (i = 0, sp = dp = row; i < row_width; i++) |
|
397 { |
|
398 png_byte save = *(sp++); |
|
399 *(dp++) = *(sp++); |
|
400 *(dp++) = save; |
|
401 } |
|
402 } |
|
403 /* This converts from AAGG to GGAA */ |
|
404 else |
|
405 { |
|
406 png_bytep sp, dp; |
|
407 png_uint_32 i; |
|
408 png_uint_32 row_width = row_info->width; |
|
409 |
|
410 for (i = 0, sp = dp = row; i < row_width; i++) |
|
411 { |
|
412 png_byte save[2]; |
|
413 save[0] = *(sp++); |
|
414 save[1] = *(sp++); |
|
415 *(dp++) = *(sp++); |
|
416 *(dp++) = *(sp++); |
|
417 *(dp++) = save[0]; |
|
418 *(dp++) = save[1]; |
|
419 } |
|
420 } |
|
421 } |
|
422 } |
|
423 } |
|
424 #endif |
|
425 |
|
426 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) |
|
427 void /* PRIVATE */ |
|
428 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) |
|
429 { |
|
430 png_debug(1, "in png_do_write_invert_alpha"); |
|
431 #if defined(PNG_USELESS_TESTS_SUPPORTED) |
|
432 if (row != NULL && row_info != NULL) |
|
433 #endif |
|
434 { |
|
435 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
|
436 { |
|
437 /* This inverts the alpha channel in RGBA */ |
|
438 if (row_info->bit_depth == 8) |
|
439 { |
|
440 png_bytep sp, dp; |
|
441 png_uint_32 i; |
|
442 png_uint_32 row_width = row_info->width; |
|
443 for (i = 0, sp = dp = row; i < row_width; i++) |
|
444 { |
|
445 /* Does nothing |
|
446 *(dp++) = *(sp++); |
|
447 *(dp++) = *(sp++); |
|
448 *(dp++) = *(sp++); |
|
449 */ |
|
450 sp+=3; dp = sp; |
|
451 *(dp++) = (png_byte)(255 - *(sp++)); |
|
452 } |
|
453 } |
|
454 /* This inverts the alpha channel in RRGGBBAA */ |
|
455 else |
|
456 { |
|
457 png_bytep sp, dp; |
|
458 png_uint_32 i; |
|
459 png_uint_32 row_width = row_info->width; |
|
460 |
|
461 for (i = 0, sp = dp = row; i < row_width; i++) |
|
462 { |
|
463 /* Does nothing |
|
464 *(dp++) = *(sp++); |
|
465 *(dp++) = *(sp++); |
|
466 *(dp++) = *(sp++); |
|
467 *(dp++) = *(sp++); |
|
468 *(dp++) = *(sp++); |
|
469 *(dp++) = *(sp++); |
|
470 */ |
|
471 sp+=6; dp = sp; |
|
472 *(dp++) = (png_byte)(255 - *(sp++)); |
|
473 *(dp++) = (png_byte)(255 - *(sp++)); |
|
474 } |
|
475 } |
|
476 } |
|
477 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) |
|
478 { |
|
479 /* This inverts the alpha channel in GA */ |
|
480 if (row_info->bit_depth == 8) |
|
481 { |
|
482 png_bytep sp, dp; |
|
483 png_uint_32 i; |
|
484 png_uint_32 row_width = row_info->width; |
|
485 |
|
486 for (i = 0, sp = dp = row; i < row_width; i++) |
|
487 { |
|
488 *(dp++) = *(sp++); |
|
489 *(dp++) = (png_byte)(255 - *(sp++)); |
|
490 } |
|
491 } |
|
492 /* This inverts the alpha channel in GGAA */ |
|
493 else |
|
494 { |
|
495 png_bytep sp, dp; |
|
496 png_uint_32 i; |
|
497 png_uint_32 row_width = row_info->width; |
|
498 |
|
499 for (i = 0, sp = dp = row; i < row_width; i++) |
|
500 { |
|
501 /* Does nothing |
|
502 *(dp++) = *(sp++); |
|
503 *(dp++) = *(sp++); |
|
504 */ |
|
505 sp+=2; dp = sp; |
|
506 *(dp++) = (png_byte)(255 - *(sp++)); |
|
507 *(dp++) = (png_byte)(255 - *(sp++)); |
|
508 } |
|
509 } |
|
510 } |
|
511 } |
|
512 } |
|
513 #endif |
|
514 |
|
515 #if defined(PNG_MNG_FEATURES_SUPPORTED) |
|
516 /* Undoes intrapixel differencing */ |
|
517 void /* PRIVATE */ |
|
518 png_do_write_intrapixel(png_row_infop row_info, png_bytep row) |
|
519 { |
|
520 png_debug(1, "in png_do_write_intrapixel"); |
|
521 if ( |
|
522 #if defined(PNG_USELESS_TESTS_SUPPORTED) |
|
523 row != NULL && row_info != NULL && |
|
524 #endif |
|
525 (row_info->color_type & PNG_COLOR_MASK_COLOR)) |
|
526 { |
|
527 int bytes_per_pixel; |
|
528 png_uint_32 row_width = row_info->width; |
|
529 if (row_info->bit_depth == 8) |
|
530 { |
|
531 png_bytep rp; |
|
532 png_uint_32 i; |
|
533 |
|
534 if (row_info->color_type == PNG_COLOR_TYPE_RGB) |
|
535 bytes_per_pixel = 3; |
|
536 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
|
537 bytes_per_pixel = 4; |
|
538 else |
|
539 return; |
|
540 |
|
541 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
|
542 { |
|
543 *(rp) = (png_byte)((*rp - *(rp+1))&0xff); |
|
544 *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); |
|
545 } |
|
546 } |
|
547 else if (row_info->bit_depth == 16) |
|
548 { |
|
549 png_bytep rp; |
|
550 png_uint_32 i; |
|
551 |
|
552 if (row_info->color_type == PNG_COLOR_TYPE_RGB) |
|
553 bytes_per_pixel = 6; |
|
554 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) |
|
555 bytes_per_pixel = 8; |
|
556 else |
|
557 return; |
|
558 |
|
559 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
|
560 { |
|
561 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); |
|
562 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); |
|
563 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); |
|
564 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); |
|
565 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); |
|
566 *(rp ) = (png_byte)((red >> 8) & 0xff); |
|
567 *(rp+1) = (png_byte)(red & 0xff); |
|
568 *(rp+4) = (png_byte)((blue >> 8) & 0xff); |
|
569 *(rp+5) = (png_byte)(blue & 0xff); |
|
570 } |
|
571 } |
|
572 } |
|
573 } |
|
574 #endif /* PNG_MNG_FEATURES_SUPPORTED */ |
|
575 #endif /* PNG_WRITE_SUPPORTED */ |