Mercurial > fife-parpg
comparison ext/libpng-1.2.29/pngwtran.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 | |
2 /* pngwtran.c - transforms the data in a row for PNG writers | |
3 * | |
4 * Last changed in libpng 1.2.9 April 14, 2006 | |
5 * For conditions of distribution and use, see copyright notice in png.h | |
6 * Copyright (c) 1998-2006 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 */ | |
18 void /* PRIVATE */ | |
19 png_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_SWAP_ALPHA_SUPPORTED) | |
64 if (png_ptr->transformations & PNG_SWAP_ALPHA) | |
65 png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); | |
66 #endif | |
67 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) | |
68 if (png_ptr->transformations & PNG_INVERT_ALPHA) | |
69 png_do_write_invert_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 */ | |
86 void /* PRIVATE */ | |
87 png_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 = PNG_ROWBYTES(row_info->pixel_depth, | |
199 row_info->width); | |
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 */ | |
212 void /* PRIVATE */ | |
213 png_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) | |
336 void /* PRIVATE */ | |
337 png_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) | |
424 void /* PRIVATE */ | |
425 png_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 /* does nothing | |
443 *(dp++) = *(sp++); | |
444 *(dp++) = *(sp++); | |
445 *(dp++) = *(sp++); | |
446 */ | |
447 sp+=3; dp = sp; | |
448 *(dp++) = (png_byte)(255 - *(sp++)); | |
449 } | |
450 } | |
451 /* This inverts the alpha channel in RRGGBBAA */ | |
452 else | |
453 { | |
454 png_bytep sp, dp; | |
455 png_uint_32 i; | |
456 png_uint_32 row_width = row_info->width; | |
457 | |
458 for (i = 0, sp = dp = row; i < row_width; i++) | |
459 { | |
460 /* does nothing | |
461 *(dp++) = *(sp++); | |
462 *(dp++) = *(sp++); | |
463 *(dp++) = *(sp++); | |
464 *(dp++) = *(sp++); | |
465 *(dp++) = *(sp++); | |
466 *(dp++) = *(sp++); | |
467 */ | |
468 sp+=6; dp = sp; | |
469 *(dp++) = (png_byte)(255 - *(sp++)); | |
470 *(dp++) = (png_byte)(255 - *(sp++)); | |
471 } | |
472 } | |
473 } | |
474 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
475 { | |
476 /* This inverts the alpha channel in GA */ | |
477 if (row_info->bit_depth == 8) | |
478 { | |
479 png_bytep sp, dp; | |
480 png_uint_32 i; | |
481 png_uint_32 row_width = row_info->width; | |
482 | |
483 for (i = 0, sp = dp = row; i < row_width; i++) | |
484 { | |
485 *(dp++) = *(sp++); | |
486 *(dp++) = (png_byte)(255 - *(sp++)); | |
487 } | |
488 } | |
489 /* This inverts the alpha channel in GGAA */ | |
490 else | |
491 { | |
492 png_bytep sp, dp; | |
493 png_uint_32 i; | |
494 png_uint_32 row_width = row_info->width; | |
495 | |
496 for (i = 0, sp = dp = row; i < row_width; i++) | |
497 { | |
498 /* does nothing | |
499 *(dp++) = *(sp++); | |
500 *(dp++) = *(sp++); | |
501 */ | |
502 sp+=2; dp = sp; | |
503 *(dp++) = (png_byte)(255 - *(sp++)); | |
504 *(dp++) = (png_byte)(255 - *(sp++)); | |
505 } | |
506 } | |
507 } | |
508 } | |
509 } | |
510 #endif | |
511 | |
512 #if defined(PNG_MNG_FEATURES_SUPPORTED) | |
513 /* undoes intrapixel differencing */ | |
514 void /* PRIVATE */ | |
515 png_do_write_intrapixel(png_row_infop row_info, png_bytep row) | |
516 { | |
517 png_debug(1, "in png_do_write_intrapixel\n"); | |
518 if ( | |
519 #if defined(PNG_USELESS_TESTS_SUPPORTED) | |
520 row != NULL && row_info != NULL && | |
521 #endif | |
522 (row_info->color_type & PNG_COLOR_MASK_COLOR)) | |
523 { | |
524 int bytes_per_pixel; | |
525 png_uint_32 row_width = row_info->width; | |
526 if (row_info->bit_depth == 8) | |
527 { | |
528 png_bytep rp; | |
529 png_uint_32 i; | |
530 | |
531 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
532 bytes_per_pixel = 3; | |
533 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
534 bytes_per_pixel = 4; | |
535 else | |
536 return; | |
537 | |
538 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
539 { | |
540 *(rp) = (png_byte)((*rp - *(rp+1))&0xff); | |
541 *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); | |
542 } | |
543 } | |
544 else if (row_info->bit_depth == 16) | |
545 { | |
546 png_bytep rp; | |
547 png_uint_32 i; | |
548 | |
549 if (row_info->color_type == PNG_COLOR_TYPE_RGB) | |
550 bytes_per_pixel = 6; | |
551 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
552 bytes_per_pixel = 8; | |
553 else | |
554 return; | |
555 | |
556 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) | |
557 { | |
558 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); | |
559 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); | |
560 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); | |
561 png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); | |
562 png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); | |
563 *(rp ) = (png_byte)((red >> 8) & 0xff); | |
564 *(rp+1) = (png_byte)(red & 0xff); | |
565 *(rp+4) = (png_byte)((blue >> 8) & 0xff); | |
566 *(rp+5) = (png_byte)(blue & 0xff); | |
567 } | |
568 } | |
569 } | |
570 } | |
571 #endif /* PNG_MNG_FEATURES_SUPPORTED */ | |
572 #endif /* PNG_WRITE_SUPPORTED */ |