1 /*
2 * PNG image format
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
26
29
30 /* TODO:
31 * - add 2, 4 and 16 bit depth support
32 */
33
34 #include <zlib.h>
35
36 #define IOBUF_SIZE 4096
37
41
46
48
51 int dpi;
///< Physical pixel density, in dots per inch, if set
52 int dpm;
///< Physical pixel density, in dots per meter, if set
54
56 int bits_per_pixel,
int pass,
58 {
59 int x,
mask, dst_x, j,
b, bpp;
62 static const int masks[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
63
65 switch(bits_per_pixel) {
66 case 1:
67 memset(dst, 0, row_size);
68 dst_x = 0;
69 for(x = 0; x <
width; x++) {
70 j = (x & 7);
71 if ((mask << j) & 0x80) {
72 b = (src[x >> 3] >> (7 - j)) & 1;
73 dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
74 dst_x++;
75 }
76 }
77 break;
78 default:
79 bpp = bits_per_pixel >> 3;
80 d = dst;
82 for(x = 0; x <
width; x++) {
83 j = x & 7;
84 if ((mask << j) & 0x80) {
85 memcpy(d, s, bpp);
86 d += bpp;
87 }
88 s += bpp;
89 }
90 break;
91 }
92 }
93
95 {
96 int i;
97 for(i = 0; i < w; i++) {
98 int a,
b,
c, p, pa, pb, pc;
99
100 a = src[i - bpp];
101 b = top[i];
102 c = top[i - bpp];
103
106
107 pa = abs(p);
108 pb = abs(pc);
109 pc = abs(p + pc);
110
111 if (pa <= pb && pa <= pc)
113 else if (pb <= pc)
115 else
117 dst[i] = src[i] - p;
118 }
119 }
120
123 {
124 int i;
125
126 switch(filter_type) {
128 memcpy(dst, src, size);
129 break;
132 memcpy(dst, src, bpp);
133 break;
136 break;
138 for(i = 0; i < bpp; i++)
139 dst[i] = src[i] - (top[i] >> 1);
141 dst[i] = src[i] - ((src[i-bpp] + top[i]) >> 1);
142 break;
144 for(i = 0; i < bpp; i++)
145 dst[i] = src[i] - top[i];
147 break;
148 }
149 }
150
153 {
156 if(!top && pred)
159 int i;
160 int cost, bcost = INT_MAX;
161 uint8_t *buf1 = dst, *buf2 = dst + size + 16;
162 for(pred=0; pred<5; pred++) {
165 cost = 0;
166 for(i=0; i<=
size; i++)
167 cost += abs((int8_t)buf1[i]);
168 if(cost < bcost) {
169 bcost = cost;
171 }
172 }
173 return buf2;
174 } else {
177 return dst;
178 }
179 }
180
183 {
184 uint32_t crc;
186
187 bytestream_put_be32(f, length);
188 crc = crc32(0, Z_NULL, 0);
190 crc = crc32(crc, tagbuf, 4);
192 if (length > 0) {
193 crc = crc32(crc, buf, length);
194 memcpy(*f, buf, length);
196 }
197 bytestream_put_be32(f, crc);
198 }
199
200 /* XXX: do filtering */
202 {
204
207 while (s->
zstream.avail_in > 0) {
208 ret = deflate(&s->
zstream, Z_NO_FLUSH);
209 if (ret != Z_OK)
210 return -1;
211 if (s->
zstream.avail_out == 0) {
216 }
217 }
218 return 0;
219 }
220
222 const AVFrame *pict,
int *got_packet)
223 {
227 int bits_per_pixel, pass_row_size, enc_row_size;
228 int64_t max_packet_size;
229 int compression_level;
231 uint8_t *crow_base = NULL, *crow_buf, *crow;
232 uint8_t *progressive_buf = NULL;
234
235 *p = *pict;
238
242 bit_depth = 16;
244 break;
246 bit_depth = 16;
248 break;
250 bit_depth = 8;
252 break;
254 bit_depth = 8;
256 break;
258 bit_depth = 16;
260 break;
262 bit_depth = 8;
264 break;
266 bit_depth = 8;
268 break;
270 bit_depth = 1;
272 break;
274 bit_depth = 8;
276 break;
277 default:
278 return -1;
279 }
281 row_size = (avctx->
width * bits_per_pixel + 7) >> 3;
282
287 Z_DEFAULT_COMPRESSION :
289 ret = deflateInit2(&s->
zstream, compression_level,
290 Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
291 if (ret != Z_OK)
292 return -1;
293
294 enc_row_size = deflateBound(&s->
zstream, row_size);
295 max_packet_size = avctx->
height * (int64_t)(enc_row_size +
298 if (max_packet_size > INT_MAX)
302
306
308 if (!crow_base)
309 goto fail;
310 crow_buf = crow_base + 15; // pixel data should be aligned, but there's a control byte before it
311 if (is_progressive) {
312 progressive_buf =
av_malloc(row_size + 1);
313 if (!progressive_buf)
314 goto fail;
315 }
316 if (is_progressive) {
318 if (!top_buf)
319 goto fail;
320 }
321
322 /* write png header */
325
328 s->
buf[8] = bit_depth;
329 s->
buf[9] = color_type;
330 s->
buf[10] = 0;
/* compression type */
331 s->
buf[11] = 0;
/* filter type */
332 s->
buf[12] = is_progressive;
/* interlace type */
333
335
339 s->
buf[8] = 1;
/* unit specifier is meter */
340 } else {
343 s->
buf[8] = 0;
/* unit specifier is unknown */
344 }
346
347 /* put the palette if needed */
349 int has_alpha,
alpha, i;
353
354 palette = (uint32_t *)p->
data[1];
356 alpha_ptr = s->
buf + 256 * 3;
357 has_alpha = 0;
358 for(i = 0; i < 256; i++) {
359 v = palette[i];
360 alpha = v >> 24;
361 if (alpha != 0xff)
362 has_alpha = 1;
363 *alpha_ptr++ =
alpha;
364 bytestream_put_be24(&ptr, v);
365 }
367 if (has_alpha) {
369 }
370 }
371
372 /* now put each row */
375 if (is_progressive) {
377
378 for(pass = 0; pass <
NB_PASSES; pass++) {
379 /* NOTE: a pass is completely omitted if no pixels would be
380 output */
382 if (pass_row_size > 0) {
383 top = NULL;
384 for(y = 0; y < avctx->
height; y++) {
389 bits_per_pixel, pass,
391 crow =
png_choose_filter(s, crow_buf, progressive_buf, top, pass_row_size, bits_per_pixel>>3);
393 top = progressive_buf;
394 }
395 }
396 }
397 }
398 } else {
399 top = NULL;
400 for(y = 0; y < avctx->
height; y++) {
404 top = ptr;
405 }
406 }
407 /* compress last bytes */
408 for(;;) {
409 ret = deflate(&s->
zstream, Z_FINISH);
410 if (ret == Z_OK || ret == Z_STREAM_END) {
414 }
417 if (ret == Z_STREAM_END)
418 break;
419 } else {
420 goto fail;
421 }
422 }
424
427 *got_packet = 1;
428 ret = 0;
429
430 the_end:
436 fail:
437 ret = -1;
438 goto the_end;
439 }
440
443
447 break;
450 break;
453 break;
456 break;
459 }
460
464
468
473 s->
dpm = s->
dpi * 10000 / 254;
474 }
475
476 return 0;
477 }
478
479 #define OFFSET(x) offsetof(PNGEncContext, x)
480 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
484 { NULL }
485 };
486
492 };
493
509 },
512 };