ReactOS 0.4.15-dev-7670-g69b08be
pngwtran.c
Go to the documentation of this file.
1
2/* pngwtran.c - transforms the data in a row for PNG writers
3 *
4 * Copyright (c) 2018 Cosmin Truta
5 * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
6 * Copyright (c) 1996-1997 Andreas Dilger
7 * 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#include "pngpriv.h"
15
16#ifdef PNG_WRITE_SUPPORTED
17#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
18
19#ifdef PNG_WRITE_PACK_SUPPORTED
20/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
21 * row_info bit depth should be 8 (one pixel per byte). The channels
22 * should be 1 (this only happens on grayscale and paletted images).
23 */
24static void
25png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
26{
27 png_debug(1, "in png_do_pack");
28
29 if (row_info->bit_depth == 8 &&
30 row_info->channels == 1)
31 {
32 switch ((int)bit_depth)
33 {
34 case 1:
35 {
36 png_bytep sp, dp;
37 int mask, v;
39 png_uint_32 row_width = row_info->width;
40
41 sp = row;
42 dp = row;
43 mask = 0x80;
44 v = 0;
45
46 for (i = 0; i < row_width; i++)
47 {
48 if (*sp != 0)
49 v |= mask;
50
51 sp++;
52
53 if (mask > 1)
54 mask >>= 1;
55
56 else
57 {
58 mask = 0x80;
59 *dp = (png_byte)v;
60 dp++;
61 v = 0;
62 }
63 }
64
65 if (mask != 0x80)
66 *dp = (png_byte)v;
67
68 break;
69 }
70
71 case 2:
72 {
73 png_bytep sp, dp;
74 unsigned int shift;
75 int v;
77 png_uint_32 row_width = row_info->width;
78
79 sp = row;
80 dp = row;
81 shift = 6;
82 v = 0;
83
84 for (i = 0; i < row_width; i++)
85 {
86 png_byte value;
87
88 value = (png_byte)(*sp & 0x03);
89 v |= (value << shift);
90
91 if (shift == 0)
92 {
93 shift = 6;
94 *dp = (png_byte)v;
95 dp++;
96 v = 0;
97 }
98
99 else
100 shift -= 2;
101
102 sp++;
103 }
104
105 if (shift != 6)
106 *dp = (png_byte)v;
107
108 break;
109 }
110
111 case 4:
112 {
113 png_bytep sp, dp;
114 unsigned int shift;
115 int v;
117 png_uint_32 row_width = row_info->width;
118
119 sp = row;
120 dp = row;
121 shift = 4;
122 v = 0;
123
124 for (i = 0; i < row_width; i++)
125 {
126 png_byte value;
127
128 value = (png_byte)(*sp & 0x0f);
129 v |= (value << shift);
130
131 if (shift == 0)
132 {
133 shift = 4;
134 *dp = (png_byte)v;
135 dp++;
136 v = 0;
137 }
138
139 else
140 shift -= 4;
141
142 sp++;
143 }
144
145 if (shift != 4)
146 *dp = (png_byte)v;
147
148 break;
149 }
150
151 default:
152 break;
153 }
154
155 row_info->bit_depth = (png_byte)bit_depth;
156 row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
157 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
158 row_info->width);
159 }
160}
161#endif
162
163#ifdef PNG_WRITE_SHIFT_SUPPORTED
164/* Shift pixel values to take advantage of whole range. Pass the
165 * true number of bits in bit_depth. The row should be packed
166 * according to row_info->bit_depth. Thus, if you had a row of
167 * bit depth 4, but the pixels only had values from 0 to 7, you
168 * would pass 3 as bit_depth, and this routine would translate the
169 * data to 0 to 15.
170 */
171static void
172png_do_shift(png_row_infop row_info, png_bytep row,
173 png_const_color_8p bit_depth)
174{
175 png_debug(1, "in png_do_shift");
176
177 if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
178 {
179 int shift_start[4], shift_dec[4];
180 unsigned int channels = 0;
181
182 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
183 {
184 shift_start[channels] = row_info->bit_depth - bit_depth->red;
185 shift_dec[channels] = bit_depth->red;
186 channels++;
187
188 shift_start[channels] = row_info->bit_depth - bit_depth->green;
189 shift_dec[channels] = bit_depth->green;
190 channels++;
191
192 shift_start[channels] = row_info->bit_depth - bit_depth->blue;
193 shift_dec[channels] = bit_depth->blue;
194 channels++;
195 }
196
197 else
198 {
199 shift_start[channels] = row_info->bit_depth - bit_depth->gray;
200 shift_dec[channels] = bit_depth->gray;
201 channels++;
202 }
203
204 if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
205 {
206 shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
207 shift_dec[channels] = bit_depth->alpha;
208 channels++;
209 }
210
211 /* With low row depths, could only be grayscale, so one channel */
212 if (row_info->bit_depth < 8)
213 {
214 png_bytep bp = row;
215 size_t i;
216 unsigned int mask;
217 size_t row_bytes = row_info->rowbytes;
218
219 if (bit_depth->gray == 1 && row_info->bit_depth == 2)
220 mask = 0x55;
221
222 else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
223 mask = 0x11;
224
225 else
226 mask = 0xff;
227
228 for (i = 0; i < row_bytes; i++, bp++)
229 {
230 int j;
231 unsigned int v, out;
232
233 v = *bp;
234 out = 0;
235
236 for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
237 {
238 if (j > 0)
239 out |= v << j;
240
241 else
242 out |= (v >> (-j)) & mask;
243 }
244
245 *bp = (png_byte)(out & 0xff);
246 }
247 }
248
249 else if (row_info->bit_depth == 8)
250 {
251 png_bytep bp = row;
253 png_uint_32 istop = channels * row_info->width;
254
255 for (i = 0; i < istop; i++, bp++)
256 {
257 unsigned int c = i%channels;
258 int j;
259 unsigned int v, out;
260
261 v = *bp;
262 out = 0;
263
264 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
265 {
266 if (j > 0)
267 out |= v << j;
268
269 else
270 out |= v >> (-j);
271 }
272
273 *bp = (png_byte)(out & 0xff);
274 }
275 }
276
277 else
278 {
279 png_bytep bp;
281 png_uint_32 istop = channels * row_info->width;
282
283 for (bp = row, i = 0; i < istop; i++)
284 {
285 unsigned int c = i%channels;
286 int j;
287 unsigned int value, v;
288
289 v = png_get_uint_16(bp);
290 value = 0;
291
292 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
293 {
294 if (j > 0)
295 value |= v << j;
296
297 else
298 value |= v >> (-j);
299 }
300 *bp++ = (png_byte)((value >> 8) & 0xff);
301 *bp++ = (png_byte)(value & 0xff);
302 }
303 }
304 }
305}
306#endif
307
308#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
309static void
310png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
311{
312 png_debug(1, "in png_do_write_swap_alpha");
313
314 {
315 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
316 {
317 if (row_info->bit_depth == 8)
318 {
319 /* This converts from ARGB to RGBA */
320 png_bytep sp, dp;
322 png_uint_32 row_width = row_info->width;
323
324 for (i = 0, sp = dp = row; i < row_width; i++)
325 {
326 png_byte save = *(sp++);
327 *(dp++) = *(sp++);
328 *(dp++) = *(sp++);
329 *(dp++) = *(sp++);
330 *(dp++) = save;
331 }
332 }
333
334#ifdef PNG_WRITE_16BIT_SUPPORTED
335 else
336 {
337 /* This converts from AARRGGBB to RRGGBBAA */
338 png_bytep sp, dp;
340 png_uint_32 row_width = row_info->width;
341
342 for (i = 0, sp = dp = row; i < row_width; i++)
343 {
344 png_byte save[2];
345 save[0] = *(sp++);
346 save[1] = *(sp++);
347 *(dp++) = *(sp++);
348 *(dp++) = *(sp++);
349 *(dp++) = *(sp++);
350 *(dp++) = *(sp++);
351 *(dp++) = *(sp++);
352 *(dp++) = *(sp++);
353 *(dp++) = save[0];
354 *(dp++) = save[1];
355 }
356 }
357#endif /* WRITE_16BIT */
358 }
359
360 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
361 {
362 if (row_info->bit_depth == 8)
363 {
364 /* This converts from AG to GA */
365 png_bytep sp, dp;
367 png_uint_32 row_width = row_info->width;
368
369 for (i = 0, sp = dp = row; i < row_width; i++)
370 {
371 png_byte save = *(sp++);
372 *(dp++) = *(sp++);
373 *(dp++) = save;
374 }
375 }
376
377#ifdef PNG_WRITE_16BIT_SUPPORTED
378 else
379 {
380 /* This converts from AAGG to GGAA */
381 png_bytep sp, dp;
383 png_uint_32 row_width = row_info->width;
384
385 for (i = 0, sp = dp = row; i < row_width; i++)
386 {
387 png_byte save[2];
388 save[0] = *(sp++);
389 save[1] = *(sp++);
390 *(dp++) = *(sp++);
391 *(dp++) = *(sp++);
392 *(dp++) = save[0];
393 *(dp++) = save[1];
394 }
395 }
396#endif /* WRITE_16BIT */
397 }
398 }
399}
400#endif
401
402#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
403static void
404png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
405{
406 png_debug(1, "in png_do_write_invert_alpha");
407
408 {
409 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
410 {
411 if (row_info->bit_depth == 8)
412 {
413 /* This inverts the alpha channel in RGBA */
414 png_bytep sp, dp;
416 png_uint_32 row_width = row_info->width;
417
418 for (i = 0, sp = dp = row; i < row_width; i++)
419 {
420 /* Does nothing
421 *(dp++) = *(sp++);
422 *(dp++) = *(sp++);
423 *(dp++) = *(sp++);
424 */
425 sp+=3; dp = sp;
426 *dp = (png_byte)(255 - *(sp++));
427 }
428 }
429
430#ifdef PNG_WRITE_16BIT_SUPPORTED
431 else
432 {
433 /* This inverts the alpha channel in RRGGBBAA */
434 png_bytep sp, dp;
436 png_uint_32 row_width = row_info->width;
437
438 for (i = 0, sp = dp = row; i < row_width; i++)
439 {
440 /* Does nothing
441 *(dp++) = *(sp++);
442 *(dp++) = *(sp++);
443 *(dp++) = *(sp++);
444 *(dp++) = *(sp++);
445 *(dp++) = *(sp++);
446 *(dp++) = *(sp++);
447 */
448 sp+=6; dp = sp;
449 *(dp++) = (png_byte)(255 - *(sp++));
450 *dp = (png_byte)(255 - *(sp++));
451 }
452 }
453#endif /* WRITE_16BIT */
454 }
455
456 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
457 {
458 if (row_info->bit_depth == 8)
459 {
460 /* This inverts the alpha channel in GA */
461 png_bytep sp, dp;
463 png_uint_32 row_width = row_info->width;
464
465 for (i = 0, sp = dp = row; i < row_width; i++)
466 {
467 *(dp++) = *(sp++);
468 *(dp++) = (png_byte)(255 - *(sp++));
469 }
470 }
471
472#ifdef PNG_WRITE_16BIT_SUPPORTED
473 else
474 {
475 /* This inverts the alpha channel in GGAA */
476 png_bytep sp, dp;
478 png_uint_32 row_width = row_info->width;
479
480 for (i = 0, sp = dp = row; i < row_width; i++)
481 {
482 /* Does nothing
483 *(dp++) = *(sp++);
484 *(dp++) = *(sp++);
485 */
486 sp+=2; dp = sp;
487 *(dp++) = (png_byte)(255 - *(sp++));
488 *dp = (png_byte)(255 - *(sp++));
489 }
490 }
491#endif /* WRITE_16BIT */
492 }
493 }
494}
495#endif
496
497/* Transform the data according to the user's wishes. The order of
498 * transformations is significant.
499 */
500void /* PRIVATE */
501png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
502{
503 png_debug(1, "in png_do_write_transformations");
504
505 if (png_ptr == NULL)
506 return;
507
508#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
509 if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
510 if (png_ptr->write_user_transform_fn != NULL)
511 (*(png_ptr->write_user_transform_fn)) /* User write transform
512 function */
513 (png_ptr, /* png_ptr */
514 row_info, /* row_info: */
515 /* png_uint_32 width; width of row */
516 /* size_t rowbytes; number of bytes in row */
517 /* png_byte color_type; color type of pixels */
518 /* png_byte bit_depth; bit depth of samples */
519 /* png_byte channels; number of channels (1-4) */
520 /* png_byte pixel_depth; bits per pixel (depth*channels) */
521 png_ptr->row_buf + 1); /* start of pixel data for row */
522#endif
523
524#ifdef PNG_WRITE_FILLER_SUPPORTED
525 if ((png_ptr->transformations & PNG_FILLER) != 0)
526 png_do_strip_channel(row_info, png_ptr->row_buf + 1,
527 !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
528#endif
529
530#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
531 if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
532 png_do_packswap(row_info, png_ptr->row_buf + 1);
533#endif
534
535#ifdef PNG_WRITE_PACK_SUPPORTED
536 if ((png_ptr->transformations & PNG_PACK) != 0)
537 png_do_pack(row_info, png_ptr->row_buf + 1,
538 (png_uint_32)png_ptr->bit_depth);
539#endif
540
541#ifdef PNG_WRITE_SWAP_SUPPORTED
542# ifdef PNG_16BIT_SUPPORTED
543 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
544 png_do_swap(row_info, png_ptr->row_buf + 1);
545# endif
546#endif
547
548#ifdef PNG_WRITE_SHIFT_SUPPORTED
549 if ((png_ptr->transformations & PNG_SHIFT) != 0)
550 png_do_shift(row_info, png_ptr->row_buf + 1,
551 &(png_ptr->shift));
552#endif
553
554#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
555 if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
556 png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
557#endif
558
559#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
560 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
561 png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
562#endif
563
564#ifdef PNG_WRITE_BGR_SUPPORTED
565 if ((png_ptr->transformations & PNG_BGR) != 0)
566 png_do_bgr(row_info, png_ptr->row_buf + 1);
567#endif
568
569#ifdef PNG_WRITE_INVERT_SUPPORTED
570 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
571 png_do_invert(row_info, png_ptr->row_buf + 1);
572#endif
573}
574#endif /* WRITE_TRANSFORMS */
575#endif /* WRITE */
#define NULL
Definition: types.h:112
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
const GLdouble * v
Definition: gl.h:2040
const GLubyte * c
Definition: glext.h:8905
GLenum GLint GLuint mask
Definition: glext.h:6028
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define c
Definition: ke_i.h:80
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: image.c:5168
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition: image.c:5167
#define PNG_COLOR_TYPE_PALETTE
Definition: image.c:5166
static const WCHAR sp[]
Definition: suminfo.c:287
#define shift
Definition: input.c:1755
#define png_get_uint_16(buf)
Definition: png.h:2596
png_structrp png_ptr
Definition: png.h:1080
png_uint_32
Definition: png.h:1936
#define PNG_COLOR_MASK_COLOR
Definition: png.h:661
#define PNG_COLOR_MASK_ALPHA
Definition: png.h:662
png_struct *PNG_RESTRICT png_structrp
Definition: png.h:466
png_byte * png_bytep
Definition: pngconf.h:579
#define png_debug(l, m)
Definition: pngdebug.h:145
#define PNG_ROWBYTES(pixel_bits, width)
Definition: pngpriv.h:729
#define PNG_INVERT_ALPHA
Definition: pngpriv.h:652
#define PNG_SWAP_ALPHA
Definition: pngpriv.h:650
#define PNG_USER_TRANSFORM
Definition: pngpriv.h:653
#define PNG_SHIFT
Definition: pngpriv.h:636
#define PNG_FILLER
Definition: pngpriv.h:648
#define PNG_FLAG_FILLER_AFTER
Definition: pngpriv.h:677
#define PNG_INVERT_MONO
Definition: pngpriv.h:638
#define PNG_PACK
Definition: pngpriv.h:635
#define PNG_PACKSWAP
Definition: pngpriv.h:649
#define PNG_SWAP_BYTES
Definition: pngpriv.h:637
#define PNG_BGR
Definition: pngpriv.h:633
int This channels
Definition: rdpsnd_libao.c:37
static FILE * out
Definition: regtests2xml.c:44
png_byte green
Definition: png.h:500
png_byte gray
Definition: png.h:502
png_byte blue
Definition: png.h:501
png_byte red
Definition: png.h:499
png_byte alpha
Definition: png.h:503
png_uint_32 width
Definition: png.h:753
png_byte color_type
Definition: png.h:755
png_byte bit_depth
Definition: png.h:756
png_byte pixel_depth
Definition: png.h:758
png_byte channels
Definition: png.h:757
size_t rowbytes
Definition: png.h:754
Definition: pdh_main.c:94