/src/ffmpeg/libavcodec/tiffenc.c
Line | Count | Source |
1 | | /* |
2 | | * TIFF image encoder |
3 | | * Copyright (c) 2007 Bartlomiej Wolowiec |
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 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * TIFF image encoder |
25 | | * @author Bartlomiej Wolowiec |
26 | | */ |
27 | | |
28 | | #include "config.h" |
29 | | #include "libavutil/attributes.h" |
30 | | #if CONFIG_ZLIB |
31 | | #include <zlib.h> |
32 | | #endif |
33 | | |
34 | | #include "libavutil/log.h" |
35 | | #include "libavutil/mem.h" |
36 | | #include "libavutil/opt.h" |
37 | | #include "libavutil/pixdesc.h" |
38 | | #include "avcodec.h" |
39 | | #include "bytestream.h" |
40 | | #include "codec_internal.h" |
41 | | #include "encode.h" |
42 | | #include "lzw.h" |
43 | | #include "rle.h" |
44 | | #include "tiff.h" |
45 | | #include "tiff_common.h" |
46 | | #include "version.h" |
47 | | |
48 | | #define TIFF_MAX_ENTRY 32 |
49 | | |
50 | | /** sizes of various TIFF field types (string size = 1)*/ |
51 | | static const uint8_t type_sizes2[14] = { |
52 | | 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4 |
53 | | }; |
54 | | |
55 | | typedef struct TiffEncoderContext { |
56 | | AVClass *class; ///< for private options |
57 | | AVCodecContext *avctx; |
58 | | |
59 | | int width; ///< picture width |
60 | | int height; ///< picture height |
61 | | unsigned int bpp; ///< bits per pixel |
62 | | int compr; ///< compression level |
63 | | int bpp_tab_size; ///< bpp_tab size |
64 | | enum TiffPhotometric photometric_interpretation; ///< photometric interpretation |
65 | | int strips; ///< number of strips |
66 | | uint32_t *strip_sizes; |
67 | | unsigned int strip_sizes_size; |
68 | | uint32_t *strip_offsets; |
69 | | unsigned int strip_offsets_size; |
70 | | uint8_t *yuv_line; |
71 | | unsigned int yuv_line_size; |
72 | | int rps; ///< row per strip |
73 | | uint8_t entries[TIFF_MAX_ENTRY * 12]; ///< entries in header |
74 | | int num_entries; ///< number of entries |
75 | | uint8_t **buf; ///< actual position in buffer |
76 | | uint8_t *buf_start; ///< pointer to first byte in buffer |
77 | | int buf_size; ///< buffer size |
78 | | uint16_t subsampling[2]; ///< YUV subsampling factors |
79 | | struct LZWEncodeState *lzws; ///< LZW encode state |
80 | | uint32_t dpi; ///< image resolution in DPI |
81 | | } TiffEncoderContext; |
82 | | |
83 | | /** |
84 | | * Check free space in buffer. |
85 | | * |
86 | | * @param s Tiff context |
87 | | * @param need Needed bytes |
88 | | * @return 0 - ok, 1 - no free space |
89 | | */ |
90 | | static inline int check_size(TiffEncoderContext *s, uint64_t need) |
91 | 80.1k | { |
92 | 80.1k | if (s->buf_size < *s->buf - s->buf_start + need) { |
93 | 0 | *s->buf = s->buf_start + s->buf_size + 1; |
94 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Buffer is too small\n"); |
95 | 0 | return 1; |
96 | 0 | } |
97 | 80.1k | return 0; |
98 | 80.1k | } |
99 | | |
100 | | /** |
101 | | * Put n values to buffer. |
102 | | * |
103 | | * @param p pointer to pointer to output buffer |
104 | | * @param n number of values |
105 | | * @param val pointer to values |
106 | | * @param type type of values |
107 | | * @param flip = 0 - normal copy, >0 - flip |
108 | | */ |
109 | | static void tnput(uint8_t **p, int n, const uint8_t *val, enum AVTiffDataType type, |
110 | | int flip) |
111 | 209k | { |
112 | 209k | int i; |
113 | | #if HAVE_BIGENDIAN |
114 | | flip ^= ((int[]) { 0, 0, 0, 1, 3, 3, 0, 0, 1, 3, 3, 3, 7, 3 })[type]; |
115 | | #endif |
116 | 4.34M | for (i = 0; i < n * type_sizes2[type]; i++) |
117 | 4.13M | *(*p)++ = val[i ^ flip]; |
118 | 209k | } |
119 | | |
120 | | /** |
121 | | * Add entry to directory in tiff header. |
122 | | * |
123 | | * @param s Tiff context |
124 | | * @param tag tag that identifies the entry |
125 | | * @param type entry type |
126 | | * @param count the number of values |
127 | | * @param ptr_val pointer to values |
128 | | */ |
129 | | static int add_entry(TiffEncoderContext *s, enum TiffTags tag, |
130 | | enum AVTiffDataType type, int count, const void *ptr_val) |
131 | 209k | { |
132 | 209k | uint8_t *entries_ptr = s->entries + 12 * s->num_entries; |
133 | 209k | int64_t data_size = count * (int64_t)type_sizes2[type]; |
134 | | |
135 | 209k | av_assert0(s->num_entries < TIFF_MAX_ENTRY); |
136 | | |
137 | 209k | bytestream_put_le16(&entries_ptr, tag); |
138 | 209k | bytestream_put_le16(&entries_ptr, type); |
139 | 209k | bytestream_put_le32(&entries_ptr, count); |
140 | | |
141 | 209k | if (type_sizes[type] * (int64_t)count <= 4) { |
142 | 158k | tnput(&entries_ptr, count, ptr_val, type, 0); |
143 | 158k | } else { |
144 | 51.4k | int padding = (*s->buf - s->buf_start) & 1; |
145 | | |
146 | 51.4k | if (check_size(s, data_size + padding)) |
147 | 0 | return AVERROR_INVALIDDATA; |
148 | 51.4k | if (padding) |
149 | 5.21k | bytestream_put_byte(s->buf, 0); |
150 | 51.4k | bytestream_put_le32(&entries_ptr, *s->buf - s->buf_start); |
151 | 51.4k | tnput(s->buf, count, ptr_val, type, 0); |
152 | 51.4k | } |
153 | | |
154 | 209k | s->num_entries++; |
155 | 209k | return 0; |
156 | 209k | } |
157 | | |
158 | | static int add_entry1(TiffEncoderContext *s, |
159 | | enum TiffTags tag, enum AVTiffDataType type, int val) |
160 | 118k | { |
161 | 118k | uint16_t w = val; |
162 | 118k | uint32_t dw = val; |
163 | 118k | return add_entry(s, tag, type, 1, |
164 | 118k | type == AV_TIFF_SHORT ? (void *)&w : (void *)&dw); |
165 | 118k | } |
166 | | |
167 | | /** |
168 | | * Encode one strip in tiff file. |
169 | | * |
170 | | * @param s Tiff context |
171 | | * @param src input buffer |
172 | | * @param dst output buffer |
173 | | * @param n size of input buffer |
174 | | * @param compr compression method |
175 | | * @return number of output bytes. If an output error is encountered, a negative |
176 | | * value corresponding to an AVERROR error code is returned. |
177 | | */ |
178 | | static int encode_strip(TiffEncoderContext *s, const int8_t *src, |
179 | | uint8_t *dst, int n, int compr) |
180 | 2.00M | { |
181 | 2.00M | switch (compr) { |
182 | 0 | #if CONFIG_ZLIB |
183 | 0 | case TIFF_DEFLATE: |
184 | 0 | case TIFF_ADOBE_DEFLATE: |
185 | 0 | { |
186 | 0 | unsigned long zlen = s->buf_size - (*s->buf - s->buf_start); |
187 | 0 | if (compress(dst, &zlen, src, n) != Z_OK) { |
188 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Compressing failed\n"); |
189 | 0 | return AVERROR_EXTERNAL; |
190 | 0 | } |
191 | 0 | return zlen; |
192 | 0 | } |
193 | 0 | #endif |
194 | 0 | case TIFF_RAW: |
195 | 0 | if (check_size(s, n)) |
196 | 0 | return AVERROR(EINVAL); |
197 | 0 | memcpy(dst, src, n); |
198 | 0 | return n; |
199 | 2.00M | case TIFF_PACKBITS: |
200 | 2.00M | return ff_rle_encode(dst, s->buf_size - (*s->buf - s->buf_start), |
201 | 2.00M | src, 1, n, 2, 0xff, -1, 0); |
202 | 0 | case TIFF_LZW: |
203 | 0 | return ff_lzw_encode(s->lzws, src, n); |
204 | 0 | default: |
205 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Unsupported compression method: %d\n", |
206 | 0 | compr); |
207 | 0 | return AVERROR(EINVAL); |
208 | 2.00M | } |
209 | 2.00M | } |
210 | | |
211 | | static void pack_yuv(TiffEncoderContext *s, const AVFrame *p, |
212 | | uint8_t *dst, int lnum) |
213 | 722k | { |
214 | 722k | int i, j, k; |
215 | 722k | int w = (s->width - 1) / s->subsampling[0] + 1; |
216 | 722k | const uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]]; |
217 | 722k | const uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]]; |
218 | 722k | if (s->width % s->subsampling[0] || s->height % s->subsampling[1]) { |
219 | 1.50M | for (i = 0; i < w; i++) { |
220 | 3.00M | for (j = 0; j < s->subsampling[1]; j++) |
221 | 7.06M | for (k = 0; k < s->subsampling[0]; k++) |
222 | 5.21M | *dst++ = p->data[0][FFMIN(lnum + j, s->height-1) * p->linesize[0] + |
223 | 5.21M | FFMIN(i * s->subsampling[0] + k, s->width-1)]; |
224 | 1.15M | *dst++ = *pu++; |
225 | 1.15M | *dst++ = *pv++; |
226 | 1.15M | } |
227 | 364k | }else{ |
228 | 3.36M | for (i = 0; i < w; i++) { |
229 | 6.85M | for (j = 0; j < s->subsampling[1]; j++) |
230 | 8.72M | for (k = 0; k < s->subsampling[0]; k++) |
231 | 4.86M | *dst++ = p->data[0][(lnum + j) * p->linesize[0] + |
232 | 4.86M | i * s->subsampling[0] + k]; |
233 | 2.99M | *dst++ = *pu++; |
234 | 2.99M | *dst++ = *pv++; |
235 | 2.99M | } |
236 | 364k | } |
237 | 722k | } |
238 | | |
239 | | #define ADD_ENTRY(s, tag, type, count, ptr_val) \ |
240 | 91.2k | do { \ |
241 | 91.2k | ret = add_entry(s, tag, type, count, ptr_val); \ |
242 | 91.2k | if (ret < 0) \ |
243 | 91.2k | goto fail; \ |
244 | 91.2k | } while (0) |
245 | | |
246 | | #define ADD_ENTRY1(s, tag, type, val) \ |
247 | 118k | do { \ |
248 | 118k | ret = add_entry1(s, tag, type, val); \ |
249 | 118k | if (ret < 0) \ |
250 | 118k | goto fail; \ |
251 | 118k | } while (0) |
252 | | |
253 | | static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
254 | | const AVFrame *pict, int *got_packet) |
255 | 14.3k | { |
256 | 14.3k | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
257 | 14.3k | TiffEncoderContext *s = avctx->priv_data; |
258 | 14.3k | const AVFrame *const p = pict; |
259 | 14.3k | const AVFrameSideData *icc_profile; |
260 | 14.3k | int i; |
261 | 14.3k | uint8_t *ptr; |
262 | 14.3k | uint8_t *offset; |
263 | 14.3k | uint32_t strips; |
264 | 14.3k | int64_t bytes_per_row; |
265 | 14.3k | uint32_t res[2] = { s->dpi, 1 }; // image resolution (72/1) |
266 | 14.3k | uint16_t bpp_tab[4]; |
267 | 14.3k | int ret = 0; |
268 | 14.3k | int is_yuv = 0, alpha = 0; |
269 | 14.3k | int shift_h, shift_v; |
270 | 14.3k | int64_t packet_size; |
271 | 14.3k | int icc_size = 0; |
272 | | |
273 | 14.3k | s->width = avctx->width; |
274 | 14.3k | s->height = avctx->height; |
275 | 14.3k | s->subsampling[0] = 1; |
276 | 14.3k | s->subsampling[1] = 1; |
277 | | |
278 | 14.3k | if (!desc) |
279 | 0 | return AVERROR(EINVAL); |
280 | | |
281 | 14.3k | avctx->bits_per_coded_sample = |
282 | 14.3k | s->bpp = av_get_bits_per_pixel(desc); |
283 | 14.3k | s->bpp_tab_size = desc->nb_components; |
284 | | |
285 | 14.3k | switch (avctx->pix_fmt) { |
286 | 751 | case AV_PIX_FMT_RGBA64LE: |
287 | 1.86k | case AV_PIX_FMT_RGBA: |
288 | 1.86k | alpha = 1; |
289 | 1.86k | av_fallthrough; |
290 | 2.26k | case AV_PIX_FMT_RGB48LE: |
291 | 2.61k | case AV_PIX_FMT_RGB24: |
292 | 2.61k | s->photometric_interpretation = TIFF_PHOTOMETRIC_RGB; |
293 | 2.61k | break; |
294 | 1.77k | case AV_PIX_FMT_GRAY8: |
295 | 1.77k | avctx->bits_per_coded_sample = 0x28; |
296 | 1.77k | av_fallthrough; |
297 | 2.12k | case AV_PIX_FMT_GRAY8A: |
298 | 3.89k | case AV_PIX_FMT_YA16LE: |
299 | 3.89k | alpha = avctx->pix_fmt == AV_PIX_FMT_GRAY8A || avctx->pix_fmt == AV_PIX_FMT_YA16LE; |
300 | 3.89k | av_fallthrough; |
301 | 6.92k | case AV_PIX_FMT_GRAY16LE: |
302 | 7.42k | case AV_PIX_FMT_MONOBLACK: |
303 | 7.42k | s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO; |
304 | 7.42k | break; |
305 | 1.98k | case AV_PIX_FMT_PAL8: |
306 | 1.98k | s->photometric_interpretation = TIFF_PHOTOMETRIC_PALETTE; |
307 | 1.98k | break; |
308 | 690 | case AV_PIX_FMT_MONOWHITE: |
309 | 690 | s->photometric_interpretation = TIFF_PHOTOMETRIC_WHITE_IS_ZERO; |
310 | 690 | break; |
311 | 205 | case AV_PIX_FMT_YUV420P: |
312 | 430 | case AV_PIX_FMT_YUV422P: |
313 | 640 | case AV_PIX_FMT_YUV440P: |
314 | 850 | case AV_PIX_FMT_YUV444P: |
315 | 1.39k | case AV_PIX_FMT_YUV410P: |
316 | 1.62k | case AV_PIX_FMT_YUV411P: |
317 | 1.62k | av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &shift_h, &shift_v); |
318 | 1.62k | s->photometric_interpretation = TIFF_PHOTOMETRIC_YCBCR; |
319 | 1.62k | s->subsampling[0] = 1 << shift_h; |
320 | 1.62k | s->subsampling[1] = 1 << shift_v; |
321 | 1.62k | is_yuv = 1; |
322 | 1.62k | break; |
323 | 0 | default: |
324 | 0 | av_log(s->avctx, AV_LOG_ERROR, |
325 | 0 | "This colors format is not supported\n"); |
326 | 0 | return AVERROR(EINVAL); |
327 | 14.3k | } |
328 | | |
329 | 41.1k | for (i = 0; i < s->bpp_tab_size; i++) |
330 | 26.7k | bpp_tab[i] = desc->comp[i].depth; |
331 | | |
332 | 14.3k | icc_profile = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE); |
333 | 14.3k | if (icc_profile && icc_profile->size) { |
334 | 0 | if (icc_profile->size > INT_MAX) { |
335 | 0 | av_log(avctx, AV_LOG_ERROR, "ICC profile is too large\n"); |
336 | 0 | return AVERROR_INVALIDDATA; |
337 | 0 | } |
338 | 0 | icc_size = icc_profile->size; |
339 | 0 | } |
340 | | |
341 | 14.3k | if (s->compr == TIFF_DEFLATE || |
342 | 14.3k | s->compr == TIFF_ADOBE_DEFLATE || |
343 | 14.3k | s->compr == TIFF_LZW) |
344 | | // best choice for DEFLATE |
345 | 0 | s->rps = s->height; |
346 | 14.3k | else |
347 | | // suggest size of strip |
348 | 14.3k | s->rps = FFMAX(8192 / ((((int64_t)s->width * s->bpp) >> 3) + 1), 1); |
349 | | // round rps up |
350 | 14.3k | s->rps = ((s->rps - 1) / s->subsampling[1] + 1) * s->subsampling[1]; |
351 | | |
352 | 14.3k | strips = (s->height - 1) / s->rps + 1; |
353 | | |
354 | 14.3k | bytes_per_row = ((((int64_t)s->width - 1) / s->subsampling[0] + 1) * |
355 | 14.3k | s->bpp * s->subsampling[0] * s->subsampling[1] + 7) >> 3; |
356 | 14.3k | if (bytes_per_row > INT_MAX) |
357 | 0 | return AVERROR(EINVAL); |
358 | 14.3k | if (avctx->height > (INT64_MAX - FF_INPUT_BUFFER_MIN_SIZE - icc_size - |
359 | 14.3k | !!icc_size) / (2 * bytes_per_row + 4)) |
360 | 0 | return AVERROR(EINVAL); |
361 | 14.3k | packet_size = avctx->height * (2 * bytes_per_row + 4) + |
362 | 14.3k | FF_INPUT_BUFFER_MIN_SIZE + icc_size + !!icc_size; |
363 | | |
364 | 14.3k | if ((ret = ff_alloc_packet(avctx, pkt, packet_size)) < 0) |
365 | 0 | return ret; |
366 | 14.3k | ptr = pkt->data; |
367 | 14.3k | s->buf_start = pkt->data; |
368 | 14.3k | s->buf = &ptr; |
369 | 14.3k | s->buf_size = pkt->size; |
370 | | |
371 | 14.3k | if (check_size(s, 8)) { |
372 | 0 | ret = AVERROR(EINVAL); |
373 | 0 | goto fail; |
374 | 0 | } |
375 | | |
376 | | // write header |
377 | 14.3k | bytestream_put_le16(&ptr, 0x4949); |
378 | 14.3k | bytestream_put_le16(&ptr, 42); |
379 | | |
380 | 14.3k | offset = ptr; |
381 | 14.3k | bytestream_put_le32(&ptr, 0); |
382 | | |
383 | 14.3k | if (strips > INT_MAX / FFMAX(sizeof(s->strip_sizes[0]), sizeof(s->strip_offsets[0]))) { |
384 | 0 | ret = AVERROR(ENOMEM); |
385 | 0 | goto fail; |
386 | 0 | } |
387 | 14.3k | av_fast_padded_mallocz(&s->strip_sizes , &s->strip_sizes_size , sizeof(s->strip_sizes [0]) * strips); |
388 | 14.3k | av_fast_padded_mallocz(&s->strip_offsets, &s->strip_offsets_size, sizeof(s->strip_offsets[0]) * strips); |
389 | | |
390 | 14.3k | if (!s->strip_sizes || !s->strip_offsets) { |
391 | 0 | ret = AVERROR(ENOMEM); |
392 | 0 | goto fail; |
393 | 0 | } |
394 | | |
395 | 14.3k | if (is_yuv) { |
396 | 1.62k | av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, bytes_per_row); |
397 | 1.62k | if (s->yuv_line == NULL) { |
398 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n"); |
399 | 0 | ret = AVERROR(ENOMEM); |
400 | 0 | goto fail; |
401 | 0 | } |
402 | 1.62k | } |
403 | | |
404 | 14.3k | #if CONFIG_ZLIB |
405 | 14.3k | if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { |
406 | 0 | uint8_t *zbuf; |
407 | 0 | int zlen, zn; |
408 | 0 | int j; |
409 | |
|
410 | 0 | zlen = bytes_per_row * s->rps; |
411 | 0 | zbuf = av_malloc(zlen); |
412 | 0 | if (!zbuf) { |
413 | 0 | ret = AVERROR(ENOMEM); |
414 | 0 | goto fail; |
415 | 0 | } |
416 | 0 | s->strip_offsets[0] = ptr - pkt->data; |
417 | 0 | zn = 0; |
418 | 0 | for (j = 0; j < s->rps; j++) { |
419 | 0 | if (is_yuv) { |
420 | 0 | pack_yuv(s, p, s->yuv_line, j); |
421 | 0 | memcpy(zbuf + zn, s->yuv_line, bytes_per_row); |
422 | 0 | j += s->subsampling[1] - 1; |
423 | 0 | } else |
424 | 0 | memcpy(zbuf + j * bytes_per_row, |
425 | 0 | p->data[0] + j * p->linesize[0], bytes_per_row); |
426 | 0 | zn += bytes_per_row; |
427 | 0 | } |
428 | 0 | ret = encode_strip(s, zbuf, ptr, zn, s->compr); |
429 | 0 | av_free(zbuf); |
430 | 0 | if (ret < 0) { |
431 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); |
432 | 0 | goto fail; |
433 | 0 | } |
434 | 0 | ptr += ret; |
435 | 0 | s->strip_sizes[0] = ptr - pkt->data - s->strip_offsets[0]; |
436 | 0 | } else |
437 | 14.3k | #endif |
438 | 14.3k | { |
439 | 14.3k | if (s->compr == TIFF_LZW) { |
440 | 0 | s->lzws = av_malloc(ff_lzw_encode_state_size); |
441 | 0 | if (!s->lzws) { |
442 | 0 | ret = AVERROR(ENOMEM); |
443 | 0 | goto fail; |
444 | 0 | } |
445 | 0 | } |
446 | 2.02M | for (i = 0; i < s->height; i++) { |
447 | 2.00M | if (s->strip_sizes[i / s->rps] == 0) { |
448 | 21.2k | if (s->compr == TIFF_LZW) { |
449 | 0 | ff_lzw_encode_init(s->lzws, ptr, |
450 | 0 | s->buf_size - (*s->buf - s->buf_start), |
451 | 0 | 12, FF_LZW_TIFF, 0); |
452 | 0 | } |
453 | 21.2k | s->strip_offsets[i / s->rps] = ptr - pkt->data; |
454 | 21.2k | } |
455 | 2.00M | if (is_yuv) { |
456 | 722k | pack_yuv(s, p, s->yuv_line, i); |
457 | 722k | ret = encode_strip(s, s->yuv_line, ptr, bytes_per_row, s->compr); |
458 | 722k | i += s->subsampling[1] - 1; |
459 | 722k | } else |
460 | 1.28M | ret = encode_strip(s, p->data[0] + i * p->linesize[0], |
461 | 1.28M | ptr, bytes_per_row, s->compr); |
462 | 2.00M | if (ret < 0) { |
463 | 0 | av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); |
464 | 0 | goto fail; |
465 | 0 | } |
466 | 2.00M | s->strip_sizes[i / s->rps] += ret; |
467 | 2.00M | ptr += ret; |
468 | 2.00M | if (s->compr == TIFF_LZW && |
469 | 0 | (i == s->height - 1 || i % s->rps == s->rps - 1)) { |
470 | 0 | ret = ff_lzw_encode_flush(s->lzws); |
471 | 0 | s->strip_sizes[(i / s->rps)] += ret; |
472 | 0 | ptr += ret; |
473 | 0 | } |
474 | 2.00M | } |
475 | 14.3k | if (s->compr == TIFF_LZW) |
476 | 0 | av_freep(&s->lzws); |
477 | 14.3k | } |
478 | | |
479 | 14.3k | s->num_entries = 0; |
480 | | |
481 | 14.3k | ADD_ENTRY1(s, TIFF_SUBFILE, AV_TIFF_LONG, 0); |
482 | 14.3k | ADD_ENTRY1(s, TIFF_WIDTH, AV_TIFF_LONG, s->width); |
483 | 14.3k | ADD_ENTRY1(s, TIFF_HEIGHT, AV_TIFF_LONG, s->height); |
484 | | |
485 | 14.3k | if (s->bpp_tab_size) |
486 | 14.3k | ADD_ENTRY(s, TIFF_BPP, AV_TIFF_SHORT, s->bpp_tab_size, bpp_tab); |
487 | | |
488 | 14.3k | ADD_ENTRY1(s, TIFF_COMPR, AV_TIFF_SHORT, s->compr); |
489 | 14.3k | ADD_ENTRY1(s, TIFF_PHOTOMETRIC, AV_TIFF_SHORT, s->photometric_interpretation); |
490 | 14.3k | ADD_ENTRY(s, TIFF_STRIP_OFFS, AV_TIFF_LONG, strips, s->strip_offsets); |
491 | | |
492 | 14.3k | AVFrameSideData *sd = av_frame_get_side_data(pict, AV_FRAME_DATA_DISPLAYMATRIX); |
493 | 14.3k | if (sd) { |
494 | 0 | int orientation = av_exif_matrix_to_orientation((int32_t *) sd->data); |
495 | 0 | if (orientation >= 1 && orientation <= 8) |
496 | 0 | ADD_ENTRY1(s, TIFF_ORIENTATION, AV_TIFF_SHORT, orientation); |
497 | 0 | } |
498 | | |
499 | 14.3k | if (s->bpp_tab_size) |
500 | 14.3k | ADD_ENTRY1(s, TIFF_SAMPLES_PER_PIXEL, AV_TIFF_SHORT, s->bpp_tab_size); |
501 | | |
502 | 14.3k | ADD_ENTRY1(s, TIFF_ROWSPERSTRIP, AV_TIFF_LONG, s->rps); |
503 | 14.3k | ADD_ENTRY(s, TIFF_STRIP_SIZE, AV_TIFF_LONG, strips, s->strip_sizes); |
504 | 14.3k | ADD_ENTRY(s, TIFF_XRES, AV_TIFF_RATIONAL, 1, res); |
505 | 14.3k | if (avctx->sample_aspect_ratio.num > 0 && |
506 | 0 | avctx->sample_aspect_ratio.den > 0) { |
507 | 0 | AVRational y = av_mul_q(av_make_q(s->dpi, 1), |
508 | 0 | avctx->sample_aspect_ratio); |
509 | 0 | res[0] = y.num; |
510 | 0 | res[1] = y.den; |
511 | 0 | } |
512 | 14.3k | ADD_ENTRY(s, TIFF_YRES, AV_TIFF_RATIONAL, 1, res); |
513 | 14.3k | ADD_ENTRY1(s, TIFF_RES_UNIT, AV_TIFF_SHORT, 2); |
514 | | |
515 | 14.3k | if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) |
516 | 14.3k | ADD_ENTRY(s, TIFF_SOFTWARE_NAME, AV_TIFF_STRING, |
517 | 14.3k | strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT); |
518 | | |
519 | 14.3k | if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { |
520 | 1.98k | uint16_t pal[256 * 3]; |
521 | 510k | for (i = 0; i < 256; i++) { |
522 | 508k | uint32_t rgb = *(uint32_t *) (p->data[1] + i * 4); |
523 | 508k | pal[i] = ((rgb >> 16) & 0xff) * 257; |
524 | 508k | pal[i + 256] = ((rgb >> 8) & 0xff) * 257; |
525 | 508k | pal[i + 512] = (rgb & 0xff) * 257; |
526 | 508k | } |
527 | 1.98k | ADD_ENTRY(s, TIFF_PAL, AV_TIFF_SHORT, 256 * 3, pal); |
528 | 1.98k | } |
529 | 14.3k | if (alpha) |
530 | 3.97k | ADD_ENTRY1(s,TIFF_EXTRASAMPLES, AV_TIFF_SHORT, 2); |
531 | 14.3k | if (is_yuv) { |
532 | | /** according to CCIR Recommendation 601.1 */ |
533 | 1.62k | uint32_t refbw[12] = { 15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1 }; |
534 | 1.62k | ADD_ENTRY(s, TIFF_YCBCR_SUBSAMPLING, AV_TIFF_SHORT, 2, s->subsampling); |
535 | 1.62k | if (avctx->chroma_sample_location == AVCHROMA_LOC_TOPLEFT) |
536 | 0 | ADD_ENTRY1(s, TIFF_YCBCR_POSITIONING, AV_TIFF_SHORT, 2); |
537 | 1.62k | ADD_ENTRY(s, TIFF_REFERENCE_BW, AV_TIFF_RATIONAL, 6, refbw); |
538 | 1.62k | } |
539 | | |
540 | 14.3k | if (icc_size) |
541 | 0 | ADD_ENTRY(s, TIFF_ICC_PROFILE, AV_TIFF_UNDEFINED, icc_size, icc_profile->data); |
542 | | |
543 | | // write offset to dir |
544 | 14.3k | bytestream_put_le32(&offset, ptr - pkt->data); |
545 | | |
546 | 14.3k | if (check_size(s, 6 + s->num_entries * 12)) { |
547 | 0 | ret = AVERROR(EINVAL); |
548 | 0 | goto fail; |
549 | 0 | } |
550 | 14.3k | bytestream_put_le16(&ptr, s->num_entries); // write tag count |
551 | 14.3k | bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12); |
552 | 14.3k | bytestream_put_le32(&ptr, 0); |
553 | | |
554 | 14.3k | pkt->size = ptr - pkt->data; |
555 | 14.3k | *got_packet = 1; |
556 | | |
557 | 14.3k | fail: |
558 | 14.3k | return ret < 0 ? ret : 0; |
559 | 14.3k | } |
560 | | |
561 | | static av_cold int encode_init(AVCodecContext *avctx) |
562 | 489 | { |
563 | 489 | TiffEncoderContext *s = avctx->priv_data; |
564 | | |
565 | | #if !CONFIG_ZLIB |
566 | | if (s->compr == TIFF_DEFLATE) { |
567 | | av_log(avctx, AV_LOG_ERROR, |
568 | | "Deflate compression needs zlib compiled in\n"); |
569 | | return AVERROR(ENOSYS); |
570 | | } |
571 | | #endif |
572 | | |
573 | 489 | s->avctx = avctx; |
574 | | |
575 | 489 | return 0; |
576 | 489 | } |
577 | | |
578 | | static av_cold int encode_close(AVCodecContext *avctx) |
579 | 489 | { |
580 | 489 | TiffEncoderContext *s = avctx->priv_data; |
581 | | |
582 | 489 | av_freep(&s->strip_sizes); |
583 | 489 | av_freep(&s->strip_offsets); |
584 | 489 | av_freep(&s->yuv_line); |
585 | | |
586 | 489 | return 0; |
587 | 489 | } |
588 | | |
589 | | #define OFFSET(x) offsetof(TiffEncoderContext, x) |
590 | | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
591 | | static const AVOption options[] = { |
592 | | {"dpi", "set the image resolution (in dpi)", OFFSET(dpi), AV_OPT_TYPE_INT, {.i64 = 72}, 1, 0x10000, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM}, |
593 | | { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, { .i64 = TIFF_PACKBITS }, TIFF_RAW, TIFF_DEFLATE, VE, .unit = "compression_algo" }, |
594 | | { "packbits", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_PACKBITS }, 0, 0, VE, .unit = "compression_algo" }, |
595 | | { "raw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_RAW }, 0, 0, VE, .unit = "compression_algo" }, |
596 | | { "lzw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_LZW }, 0, 0, VE, .unit = "compression_algo" }, |
597 | | { "deflate", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_DEFLATE }, 0, 0, VE, .unit = "compression_algo" }, |
598 | | { NULL }, |
599 | | }; |
600 | | |
601 | | static const AVClass tiffenc_class = { |
602 | | .class_name = "TIFF encoder", |
603 | | .item_name = av_default_item_name, |
604 | | .option = options, |
605 | | .version = LIBAVUTIL_VERSION_INT, |
606 | | }; |
607 | | |
608 | | const FFCodec ff_tiff_encoder = { |
609 | | .p.name = "tiff", |
610 | | CODEC_LONG_NAME("TIFF image"), |
611 | | .p.type = AVMEDIA_TYPE_VIDEO, |
612 | | .p.id = AV_CODEC_ID_TIFF, |
613 | | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | |
614 | | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, |
615 | | .caps_internal = FF_CODEC_CAP_ICC_PROFILES, |
616 | | .priv_data_size = sizeof(TiffEncoderContext), |
617 | | .init = encode_init, |
618 | | .close = encode_close, |
619 | | FF_CODEC_ENCODE_CB(encode_frame), |
620 | | CODEC_PIXFMTS( |
621 | | AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8, |
622 | | AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64LE, |
623 | | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_YA16LE, |
624 | | AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_MONOWHITE, |
625 | | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, |
626 | | AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P), |
627 | | .color_ranges = AVCOL_RANGE_MPEG, |
628 | | .p.priv_class = &tiffenc_class, |
629 | | }; |