]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngwtran.c
* Added $(THREADS_LINK) to $(LINK_LIBS) so all programs can be linked.
[wxWidgets.git] / src / png / pngwtran.c
CommitLineData
c801d85f
KB
1
2/* pngwtran.c - transforms the data in a row for PNG writers
3 *
4 * libpng 1.0.1
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
8 * Copyright (c) 1998, Glenn Randers-Pehrson
9 * March 15, 1998
10 */
11
12#define PNG_INTERNAL
13#include "png.h"
14
15/* Transform the data according to the users wishes. The order of
16 * transformations is significant.
17 */
18void
19png_do_write_transformations(png_structp png_ptr)
20{
21 png_debug(1, "in png_do_write_transformations\n");
22
23#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
24 if (png_ptr->transformations & PNG_USER_TRANSFORM)
25 if(png_ptr->write_user_transform_fn != NULL)
26 (*(png_ptr->write_user_transform_fn)) /* user write transform function */
27 (png_ptr, /* png_ptr */
28 &(png_ptr->row_info), /* row_info: */
29 /* png_uint_32 width; width of row */
30 /* png_uint_32 rowbytes; number of bytes in row */
31 /* png_byte color_type; color type of pixels */
32 /* png_byte bit_depth; bit depth of samples */
33 /* png_byte channels; number of channels (1-4) */
34 /* png_byte pixel_depth; bits per pixel (depth*channels) */
35 png_ptr->row_buf + 1); /* start of pixel data for row */
36#endif
37#if defined(PNG_WRITE_FILLER_SUPPORTED)
38 if (png_ptr->transformations & PNG_FILLER)
39 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
40 png_ptr->flags);
41#endif
42#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
43 if (png_ptr->transformations & PNG_PACKSWAP)
44 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
45#endif
46#if defined(PNG_WRITE_PACK_SUPPORTED)
47 if (png_ptr->transformations & PNG_PACK)
48 png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
49 (png_uint_32)png_ptr->bit_depth);
50#endif
51#if defined(PNG_WRITE_SHIFT_SUPPORTED)
52 if (png_ptr->transformations & PNG_SHIFT)
53 png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
54 &(png_ptr->shift));
55#endif
56#if defined(PNG_WRITE_SWAP_SUPPORTED)
57 if (png_ptr->transformations & PNG_SWAP_BYTES)
58 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
59#endif
60#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
61 if (png_ptr->transformations & PNG_INVERT_ALPHA)
62 png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
63#endif
64#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
65 if (png_ptr->transformations & PNG_SWAP_ALPHA)
66 png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
67#endif
68#if defined(PNG_WRITE_BGR_SUPPORTED)
69 if (png_ptr->transformations & PNG_BGR)
70 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
71#endif
72#if defined(PNG_WRITE_INVERT_SUPPORTED)
73 if (png_ptr->transformations & PNG_INVERT_MONO)
74 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
75#endif
76}
77
78#if defined(PNG_WRITE_PACK_SUPPORTED)
79/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
80 * row_info bit depth should be 8 (one pixel per byte). The channels
81 * should be 1 (this only happens on grayscale and paletted images).
82 */
83void
84png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
85{
86 png_debug(1, "in png_do_pack\n");
87 if (row_info->bit_depth == 8 &&
88#if defined(PNG_USELESS_TESTS_SUPPORTED)
89 row != NULL && row_info != NULL &&
90#endif
91 row_info->channels == 1)
92 {
93 switch ((int)bit_depth)
94 {
95 case 1:
96 {
97 png_bytep sp, dp;
98 int mask, v;
99 png_uint_32 i;
100
101 sp = row;
102 dp = row;
103 mask = 0x80;
104 v = 0;
105 for (i = 0; i < row_info->width; i++)
106 {
107 if (*sp != 0)
108 v |= mask;
109 sp++;
110 if (mask > 1)
111 mask >>= 1;
112 else
113 {
114 mask = 0x80;
115 *dp = (png_byte)v;
116 dp++;
117 v = 0;
118 }
119 }
120 if (mask != 0x80)
121 *dp = (png_byte)v;
122 break;
123 }
124 case 2:
125 {
126 png_bytep sp, dp;
127 int shift, v;
128 png_uint_32 i;
129
130 sp = row;
131 dp = row;
132 shift = 6;
133 v = 0;
134 for (i = 0; i < row_info->width; i++)
135 {
136 png_byte value;
137
138 value = (png_byte)(*sp & 0x3);
139 v |= (value << shift);
140 if (shift == 0)
141 {
142 shift = 6;
143 *dp = (png_byte)v;
144 dp++;
145 v = 0;
146 }
147 else
148 shift -= 2;
149 sp++;
150 }
151 if (shift != 6)
152 *dp = (png_byte)v;
153 break;
154 }
155 case 4:
156 {
157 png_bytep sp, dp;
158 int shift, v;
159 png_uint_32 i;
160
161 sp = row;
162 dp = row;
163 shift = 4;
164 v = 0;
165 for (i = 0; i < row_info->width; i++)
166 {
167 png_byte value;
168
169 value = (png_byte)(*sp & 0xf);
170 v |= (value << shift);
171
172 if (shift == 0)
173 {
174 shift = 4;
175 *dp = (png_byte)v;
176 dp++;
177 v = 0;
178 }
179 else
180 shift -= 4;
181
182 sp++;
183 }
184 if (shift != 4)
185 *dp = (png_byte)v;
186 break;
187 }
188 }
189 row_info->bit_depth = (png_byte)bit_depth;
190 row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
191 row_info->rowbytes =
192 ((row_info->width * row_info->pixel_depth + 7) >> 3);
193 }
194}
195#endif
196
197#if defined(PNG_WRITE_SHIFT_SUPPORTED)
198/* Shift pixel values to take advantage of whole range. Pass the
199 * true number of bits in bit_depth. The row should be packed
200 * according to row_info->bit_depth. Thus, if you had a row of
201 * bit depth 4, but the pixels only had values from 0 to 7, you
202 * would pass 3 as bit_depth, and this routine would translate the
203 * data to 0 to 15.
204 */
205void
206png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
207{
208 png_debug(1, "in png_do_shift\n");
209#if defined(PNG_USELESS_TESTS_SUPPORTED)
210 if (row != NULL && row_info != NULL &&
211#else
212 if (
213#endif
214 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
215 {
216 int shift_start[4], shift_dec[4];
217 png_uint_32 channels;
218
219 channels = 0;
220 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
221 {
222 shift_start[channels] = row_info->bit_depth - bit_depth->red;
223 shift_dec[channels] = bit_depth->red;
224 channels++;
225 shift_start[channels] = row_info->bit_depth - bit_depth->green;
226 shift_dec[channels] = bit_depth->green;
227 channels++;
228 shift_start[channels] = row_info->bit_depth - bit_depth->blue;
229 shift_dec[channels] = bit_depth->blue;
230 channels++;
231 }
232 else
233 {
234 shift_start[channels] = row_info->bit_depth - bit_depth->gray;
235 shift_dec[channels] = bit_depth->gray;
236 channels++;
237 }
238 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
239 {
240 shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
241 shift_dec[channels] = bit_depth->alpha;
242 channels++;
243 }
244
245 /* with low row depths, could only be grayscale, so one channel */
246 if (row_info->bit_depth < 8)
247 {
248 png_bytep bp;
249 png_uint_32 i;
250 png_byte mask;
251
252 if (bit_depth->gray == 1 && row_info->bit_depth == 2)
253 mask = 0x55;
254 else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
255 mask = 0x11;
256 else
257 mask = 0xff;
258
259 for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
260 {
261 png_uint_16 v;
262 int j;
263
264 v = *bp;
265 *bp = 0;
266 for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
267 {
268 if (j > 0)
269 *bp |= (png_byte)((v << j) & 0xff);
270 else
271 *bp |= (png_byte)((v >> (-j)) & mask);
272 }
273 }
274 }
275 else if (row_info->bit_depth == 8)
276 {
277 png_bytep bp;
278 png_uint_32 i;
279
280 for (bp = row, i = 0; i < row_info->width; i++)
281 {
282 png_uint_32 c;
283
284 for (c = 0; c < channels; c++, bp++)
285 {
286 png_uint_16 v;
287 int j;
288
289 v = *bp;
290 *bp = 0;
291 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
292 {
293 if (j > 0)
294 *bp |= (png_byte)((v << j) & 0xff);
295 else
296 *bp |= (png_byte)((v >> (-j)) & 0xff);
297 }
298 }
299 }
300 }
301 else
302 {
303 png_bytep bp;
304 png_uint_32 i;
305
306 for (bp = row, i = 0; i < row_info->width * row_info->channels; i++)
307 {
308 png_uint_32 c;
309
310 for (c = 0; c < channels; c++, bp += 2)
311 {
312 png_uint_16 value, v;
313 int j;
314
315 v = ((png_uint_16)(*bp) << 8) + *(bp + 1);
316 value = 0;
317 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
318 {
319 if (j > 0)
320 value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
321 else
322 value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
323 }
324 *bp = (png_byte)(value >> 8);
325 *(bp + 1) = (png_byte)(value & 0xff);
326 }
327 }
328 }
329 }
330}
331#endif
332
333#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
334void
335png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
336{
337 png_debug(1, "in png_do_write_swap_alpha\n");
338#if defined(PNG_USELESS_TESTS_SUPPORTED)
339 if (row != NULL && row_info != NULL)
340#endif
341 {
342 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
343 {
344 /* This converts from ARGB to RGBA */
345 if (row_info->bit_depth == 8)
346 {
347 png_bytep sp, dp;
348 png_byte save;
349 png_uint_32 i;
350
351 for (i = 0, sp = dp = row; i < row_info->width; i++)
352 {
353 save = *(sp++);
354 *(dp++) = *(sp++);
355 *(dp++) = *(sp++);
356 *(dp++) = *(sp++);
357 *(dp++) = save;
358 }
359 }
360 /* This converts from AARRGGBB to RRGGBBAA */
361 else
362 {
363 png_bytep sp, dp;
364 png_byte save[2];
365 png_uint_32 i;
366
367 for (i = 0, sp = dp = row; i < row_info->width; i++)
368 {
369 save[0] = *(sp++);
370 save[1] = *(sp++);
371 *(dp++) = *(sp++);
372 *(dp++) = *(sp++);
373 *(dp++) = *(sp++);
374 *(dp++) = *(sp++);
375 *(dp++) = *(sp++);
376 *(dp++) = *(sp++);
377 *(dp++) = save[0];
378 *(dp++) = save[1];
379 }
380 }
381 }
382 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
383 {
384 /* This converts from AG to GA */
385 if (row_info->bit_depth == 8)
386 {
387 png_bytep sp, dp;
388 png_byte save;
389 png_uint_32 i;
390
391 for (i = 0, sp = dp = row; i < row_info->width; i++)
392 {
393 save = *(sp++);
394 *(dp++) = *(sp++);
395 *(dp++) = save;
396 }
397 }
398 /* This converts from AAGG to GGAA */
399 else
400 {
401 png_bytep sp, dp;
402 png_byte save[2];
403 png_uint_32 i;
404
405 for (i = 0, sp = dp = row; i < row_info->width; i++)
406 {
407 save[0] = *(sp++);
408 save[1] = *(sp++);
409 *(dp++) = *(sp++);
410 *(dp++) = *(sp++);
411 *(dp++) = save[0];
412 *(dp++) = save[1];
413 }
414 }
415 }
416 }
417}
418#endif
419
420#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
421void
422png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
423{
424 png_debug(1, "in png_do_write_invert_alpha\n");
425#if defined(PNG_USELESS_TESTS_SUPPORTED)
426 if (row != NULL && row_info != NULL)
427#endif
428 {
429 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
430 {
431 /* This inverts the alpha channel in RGBA */
432 if (row_info->bit_depth == 8)
433 {
434 png_bytep sp, dp;
435 png_uint_32 i;
436
437 for (i = 0, sp = dp = row; i < row_info->width; i++)
438 {
439 *(dp++) = *(sp++);
440 *(dp++) = *(sp++);
441 *(dp++) = *(sp++);
442 *(dp++) = 255 - *(sp++);
443 }
444 }
445 /* This inverts the alpha channel in RRGGBBAA */
446 else
447 {
448 png_bytep sp, dp;
449 png_uint_32 i;
450
451 for (i = 0, sp = dp = row; i < row_info->width; i++)
452 {
453 *(dp++) = *(sp++);
454 *(dp++) = *(sp++);
455 *(dp++) = *(sp++);
456 *(dp++) = *(sp++);
457 *(dp++) = *(sp++);
458 *(dp++) = *(sp++);
459 *(dp++) = 255 - *(sp++);
460 *(dp++) = 255 - *(sp++);
461 }
462 }
463 }
464 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
465 {
466 /* This inverts the alpha channel in GA */
467 if (row_info->bit_depth == 8)
468 {
469 png_bytep sp, dp;
470 png_uint_32 i;
471
472 for (i = 0, sp = dp = row; i < row_info->width; i++)
473 {
474 *(dp++) = *(sp++);
475 *(dp++) = 255 - *(sp++);
476 }
477 }
478 /* This inverts the alpha channel in GGAA */
479 else
480 {
481 png_bytep sp, dp;
482 png_uint_32 i;
483
484 for (i = 0, sp = dp = row; i < row_info->width; i++)
485 {
486 *(dp++) = *(sp++);
487 *(dp++) = *(sp++);
488 *(dp++) = 255 - *(sp++);
489 *(dp++) = 255 - *(sp++);
490 }
491 }
492 }
493 }
494}
495#endif