Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/libpng/pngwtran.c
16337 views
1
2
/* pngwtran.c - transforms the data in a row for PNG writers
3
*
4
* Last changed in libpng 1.6.26 [October 20, 2016]
5
* Copyright (c) 1998-2002,2004,2006-2016 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
#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
*/
24
static void
25
png_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;
38
png_uint_32 i;
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;
76
png_uint_32 i;
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;
116
png_uint_32 i;
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
*/
171
static void
172
png_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
png_size_t i;
216
unsigned int mask;
217
png_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;
252
png_uint_32 i;
253
png_uint_32 istop = channels * row_info->width;
254
255
for (i = 0; i < istop; i++, bp++)
256
{
257
258
const unsigned int c = i%channels;
259
int j;
260
unsigned int v, out;
261
262
v = *bp;
263
out = 0;
264
265
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
266
{
267
if (j > 0)
268
out |= v << j;
269
270
else
271
out |= v >> (-j);
272
}
273
274
*bp = (png_byte)(out & 0xff);
275
}
276
}
277
278
else
279
{
280
png_bytep bp;
281
png_uint_32 i;
282
png_uint_32 istop = channels * row_info->width;
283
284
for (bp = row, i = 0; i < istop; i++)
285
{
286
const unsigned int c = i%channels;
287
int j;
288
unsigned int value, v;
289
290
v = png_get_uint_16(bp);
291
value = 0;
292
293
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
294
{
295
if (j > 0)
296
value |= v << j;
297
298
else
299
value |= v >> (-j);
300
}
301
*bp++ = (png_byte)((value >> 8) & 0xff);
302
*bp++ = (png_byte)(value & 0xff);
303
}
304
}
305
}
306
}
307
#endif
308
309
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
310
static void
311
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
312
{
313
png_debug(1, "in png_do_write_swap_alpha");
314
315
{
316
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
317
{
318
if (row_info->bit_depth == 8)
319
{
320
/* This converts from ARGB to RGBA */
321
png_bytep sp, dp;
322
png_uint_32 i;
323
png_uint_32 row_width = row_info->width;
324
325
for (i = 0, sp = dp = row; i < row_width; i++)
326
{
327
png_byte save = *(sp++);
328
*(dp++) = *(sp++);
329
*(dp++) = *(sp++);
330
*(dp++) = *(sp++);
331
*(dp++) = save;
332
}
333
}
334
335
#ifdef PNG_WRITE_16BIT_SUPPORTED
336
else
337
{
338
/* This converts from AARRGGBB to RRGGBBAA */
339
png_bytep sp, dp;
340
png_uint_32 i;
341
png_uint_32 row_width = row_info->width;
342
343
for (i = 0, sp = dp = row; i < row_width; i++)
344
{
345
png_byte save[2];
346
save[0] = *(sp++);
347
save[1] = *(sp++);
348
*(dp++) = *(sp++);
349
*(dp++) = *(sp++);
350
*(dp++) = *(sp++);
351
*(dp++) = *(sp++);
352
*(dp++) = *(sp++);
353
*(dp++) = *(sp++);
354
*(dp++) = save[0];
355
*(dp++) = save[1];
356
}
357
}
358
#endif /* WRITE_16BIT */
359
}
360
361
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
362
{
363
if (row_info->bit_depth == 8)
364
{
365
/* This converts from AG to GA */
366
png_bytep sp, dp;
367
png_uint_32 i;
368
png_uint_32 row_width = row_info->width;
369
370
for (i = 0, sp = dp = row; i < row_width; i++)
371
{
372
png_byte save = *(sp++);
373
*(dp++) = *(sp++);
374
*(dp++) = save;
375
}
376
}
377
378
#ifdef PNG_WRITE_16BIT_SUPPORTED
379
else
380
{
381
/* This converts from AAGG to GGAA */
382
png_bytep sp, dp;
383
png_uint_32 i;
384
png_uint_32 row_width = row_info->width;
385
386
for (i = 0, sp = dp = row; i < row_width; i++)
387
{
388
png_byte save[2];
389
save[0] = *(sp++);
390
save[1] = *(sp++);
391
*(dp++) = *(sp++);
392
*(dp++) = *(sp++);
393
*(dp++) = save[0];
394
*(dp++) = save[1];
395
}
396
}
397
#endif /* WRITE_16BIT */
398
}
399
}
400
}
401
#endif
402
403
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
404
static void
405
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
406
{
407
png_debug(1, "in png_do_write_invert_alpha");
408
409
{
410
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
411
{
412
if (row_info->bit_depth == 8)
413
{
414
/* This inverts the alpha channel in RGBA */
415
png_bytep sp, dp;
416
png_uint_32 i;
417
png_uint_32 row_width = row_info->width;
418
419
for (i = 0, sp = dp = row; i < row_width; i++)
420
{
421
/* Does nothing
422
*(dp++) = *(sp++);
423
*(dp++) = *(sp++);
424
*(dp++) = *(sp++);
425
*/
426
sp+=3; dp = sp;
427
*dp = (png_byte)(255 - *(sp++));
428
}
429
}
430
431
#ifdef PNG_WRITE_16BIT_SUPPORTED
432
else
433
{
434
/* This inverts the alpha channel in RRGGBBAA */
435
png_bytep sp, dp;
436
png_uint_32 i;
437
png_uint_32 row_width = row_info->width;
438
439
for (i = 0, sp = dp = row; i < row_width; i++)
440
{
441
/* Does nothing
442
*(dp++) = *(sp++);
443
*(dp++) = *(sp++);
444
*(dp++) = *(sp++);
445
*(dp++) = *(sp++);
446
*(dp++) = *(sp++);
447
*(dp++) = *(sp++);
448
*/
449
sp+=6; dp = sp;
450
*(dp++) = (png_byte)(255 - *(sp++));
451
*dp = (png_byte)(255 - *(sp++));
452
}
453
}
454
#endif /* WRITE_16BIT */
455
}
456
457
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
458
{
459
if (row_info->bit_depth == 8)
460
{
461
/* This inverts the alpha channel in GA */
462
png_bytep sp, dp;
463
png_uint_32 i;
464
png_uint_32 row_width = row_info->width;
465
466
for (i = 0, sp = dp = row; i < row_width; i++)
467
{
468
*(dp++) = *(sp++);
469
*(dp++) = (png_byte)(255 - *(sp++));
470
}
471
}
472
473
#ifdef PNG_WRITE_16BIT_SUPPORTED
474
else
475
{
476
/* This inverts the alpha channel in GGAA */
477
png_bytep sp, dp;
478
png_uint_32 i;
479
png_uint_32 row_width = row_info->width;
480
481
for (i = 0, sp = dp = row; i < row_width; i++)
482
{
483
/* Does nothing
484
*(dp++) = *(sp++);
485
*(dp++) = *(sp++);
486
*/
487
sp+=2; dp = sp;
488
*(dp++) = (png_byte)(255 - *(sp++));
489
*dp = (png_byte)(255 - *(sp++));
490
}
491
}
492
#endif /* WRITE_16BIT */
493
}
494
}
495
}
496
#endif
497
498
/* Transform the data according to the user's wishes. The order of
499
* transformations is significant.
500
*/
501
void /* PRIVATE */
502
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
503
{
504
png_debug(1, "in png_do_write_transformations");
505
506
if (png_ptr == NULL)
507
return;
508
509
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
510
if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
511
if (png_ptr->write_user_transform_fn != NULL)
512
(*(png_ptr->write_user_transform_fn)) /* User write transform
513
function */
514
(png_ptr, /* png_ptr */
515
row_info, /* row_info: */
516
/* png_uint_32 width; width of row */
517
/* png_size_t rowbytes; number of bytes in row */
518
/* png_byte color_type; color type of pixels */
519
/* png_byte bit_depth; bit depth of samples */
520
/* png_byte channels; number of channels (1-4) */
521
/* png_byte pixel_depth; bits per pixel (depth*channels) */
522
png_ptr->row_buf + 1); /* start of pixel data for row */
523
#endif
524
525
#ifdef PNG_WRITE_FILLER_SUPPORTED
526
if ((png_ptr->transformations & PNG_FILLER) != 0)
527
png_do_strip_channel(row_info, png_ptr->row_buf + 1,
528
!(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
529
#endif
530
531
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
532
if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
533
png_do_packswap(row_info, png_ptr->row_buf + 1);
534
#endif
535
536
#ifdef PNG_WRITE_PACK_SUPPORTED
537
if ((png_ptr->transformations & PNG_PACK) != 0)
538
png_do_pack(row_info, png_ptr->row_buf + 1,
539
(png_uint_32)png_ptr->bit_depth);
540
#endif
541
542
#ifdef PNG_WRITE_SWAP_SUPPORTED
543
# ifdef PNG_16BIT_SUPPORTED
544
if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
545
png_do_swap(row_info, png_ptr->row_buf + 1);
546
# endif
547
#endif
548
549
#ifdef PNG_WRITE_SHIFT_SUPPORTED
550
if ((png_ptr->transformations & PNG_SHIFT) != 0)
551
png_do_shift(row_info, png_ptr->row_buf + 1,
552
&(png_ptr->shift));
553
#endif
554
555
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
556
if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
557
png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
558
#endif
559
560
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
561
if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
562
png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
563
#endif
564
565
#ifdef PNG_WRITE_BGR_SUPPORTED
566
if ((png_ptr->transformations & PNG_BGR) != 0)
567
png_do_bgr(row_info, png_ptr->row_buf + 1);
568
#endif
569
570
#ifdef PNG_WRITE_INVERT_SUPPORTED
571
if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
572
png_do_invert(row_info, png_ptr->row_buf + 1);
573
#endif
574
}
575
#endif /* WRITE_TRANSFORMS */
576
#endif /* WRITE */
577
578