Commit | Line | Data |
---|---|---|
716222db MN |
1 | /* |
2 | * TIFF image encoder | |
3 | * Copyright (c) 2007 Bartlomiej Wolowiec | |
4 | * | |
2912e87a | 5 | * This file is part of Libav. |
716222db | 6 | * |
2912e87a | 7 | * Libav is free software; you can redistribute it and/or |
716222db MN |
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 | * | |
2912e87a | 12 | * Libav is distributed in the hope that it will be useful, |
716222db MN |
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 | |
2912e87a | 18 | * License along with Libav; if not, write to the Free Software |
716222db | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
716222db MN |
20 | */ |
21 | ||
ee5c8a9b | 22 | /** |
ba87f080 | 23 | * @file |
f6f95d4e | 24 | * TIFF image encoder |
ee5c8a9b DB |
25 | * @author Bartlomiej Wolowiec |
26 | */ | |
f6f95d4e | 27 | |
1d9c2dc8 | 28 | #include "config.h" |
b250f9c6 | 29 | #if CONFIG_ZLIB |
716222db MN |
30 | #include <zlib.h> |
31 | #endif | |
46ce9ded DB |
32 | |
33 | #include "libavutil/log.h" | |
34 | #include "libavutil/opt.h" | |
35 | #include "libavutil/pixdesc.h" | |
36 | #include "avcodec.h" | |
716222db | 37 | #include "bytestream.h" |
efd2afc2 | 38 | #include "lzw.h" |
f38e4507 | 39 | #include "put_bits.h" |
46ce9ded DB |
40 | #include "rle.h" |
41 | #include "tiff.h" | |
716222db MN |
42 | |
43 | #define TIFF_MAX_ENTRY 32 | |
44 | ||
45 | /** sizes of various TIFF field types (string size = 1)*/ | |
46 | static const uint8_t type_sizes2[6] = { | |
47 | 0, 1, 1, 2, 4, 8 | |
48 | }; | |
49 | ||
50 | typedef struct TiffEncoderContext { | |
46ce9ded | 51 | AVClass *class; ///< for private options |
716222db | 52 | AVCodecContext *avctx; |
716222db | 53 | |
46ce9ded DB |
54 | int width; ///< picture width |
55 | int height; ///< picture height | |
56 | unsigned int bpp; ///< bits per pixel | |
57 | int compr; ///< compression level | |
58 | int bpp_tab_size; ///< bpp_tab size | |
a9b046fb | 59 | enum TiffPhotometric photometric_interpretation; ///< photometric interpretation |
46ce9ded DB |
60 | int strips; ///< number of strips |
61 | int rps; ///< row per strip | |
62 | uint8_t entries[TIFF_MAX_ENTRY * 12]; ///< entries in header | |
63 | int num_entries; ///< number of entries | |
64 | uint8_t **buf; ///< actual position in buffer | |
65 | uint8_t *buf_start; ///< pointer to first byte in buffer | |
66 | int buf_size; ///< buffer size | |
67 | uint16_t subsampling[2]; ///< YUV subsampling factors | |
68 | struct LZWEncodeState *lzws; ///< LZW encode state | |
716222db MN |
69 | } TiffEncoderContext; |
70 | ||
716222db MN |
71 | /** |
72 | * Check free space in buffer | |
73 | * @param s Tiff context | |
74 | * @param need Needed bytes | |
75 | * @return 0 - ok, 1 - no free space | |
76 | */ | |
46ce9ded | 77 | static inline int check_size(TiffEncoderContext *s, uint64_t need) |
716222db MN |
78 | { |
79 | if (s->buf_size < *s->buf - s->buf_start + need) { | |
80 | *s->buf = s->buf_start + s->buf_size + 1; | |
81 | av_log(s->avctx, AV_LOG_ERROR, "Buffer is too small\n"); | |
82 | return 1; | |
83 | } | |
84 | return 0; | |
85 | } | |
86 | ||
87 | /** | |
88 | * Put n values to buffer | |
89 | * | |
90 | * @param p Pointer to pointer to output buffer | |
91 | * @param n Number of values | |
92 | * @param val Pointer to values | |
93 | * @param type Type of values | |
94 | * @param flip =0 - normal copy, >0 - flip | |
95 | */ | |
46ce9ded | 96 | static void tnput(uint8_t **p, int n, const uint8_t *val, enum TiffTypes type, |
716222db MN |
97 | int flip) |
98 | { | |
99 | int i; | |
63613fe6 | 100 | #if HAVE_BIGENDIAN |
46ce9ded | 101 | flip ^= ((int[]) { 0, 0, 0, 1, 3, 3 })[type]; |
716222db MN |
102 | #endif |
103 | for (i = 0; i < n * type_sizes2[type]; i++) | |
104 | *(*p)++ = val[i ^ flip]; | |
105 | } | |
106 | ||
107 | /** | |
108 | * Add entry to directory in tiff header. | |
109 | * @param s Tiff context | |
110 | * @param tag Tag that identifies the entry | |
111 | * @param type Entry type | |
112 | * @param count The number of values | |
113 | * @param ptr_val Pointer to values | |
114 | */ | |
46ce9ded DB |
115 | static void add_entry(TiffEncoderContext *s, enum TiffTags tag, |
116 | enum TiffTypes type, int count, const void *ptr_val) | |
716222db MN |
117 | { |
118 | uint8_t *entries_ptr = s->entries + 12 * s->num_entries; | |
119 | ||
120 | assert(s->num_entries < TIFF_MAX_ENTRY); | |
121 | ||
122 | bytestream_put_le16(&entries_ptr, tag); | |
123 | bytestream_put_le16(&entries_ptr, type); | |
124 | bytestream_put_le32(&entries_ptr, count); | |
125 | ||
126 | if (type_sizes[type] * count <= 4) { | |
127 | tnput(&entries_ptr, count, ptr_val, type, 0); | |
128 | } else { | |
129 | bytestream_put_le32(&entries_ptr, *s->buf - s->buf_start); | |
130 | check_size(s, count * type_sizes2[type]); | |
131 | tnput(s->buf, count, ptr_val, type, 0); | |
132 | } | |
133 | ||
134 | s->num_entries++; | |
135 | } | |
136 | ||
46ce9ded DB |
137 | static void add_entry1(TiffEncoderContext *s, |
138 | enum TiffTags tag, enum TiffTypes type, int val) | |
139 | { | |
140 | uint16_t w = val; | |
141 | uint32_t dw = val; | |
6be4042c | 142 | add_entry(s, tag, type, 1, type == TIFF_SHORT ? (void *)&w : (void *)&dw); |
0a7a33d2 MN |
143 | } |
144 | ||
716222db MN |
145 | /** |
146 | * Encode one strip in tiff file | |
147 | * | |
148 | * @param s Tiff context | |
149 | * @param src Input buffer | |
150 | * @param dst Output buffer | |
151 | * @param n Size of input buffer | |
152 | * @param compr Compression method | |
153 | * @return Number of output bytes. If an output error is encountered, -1 returned | |
154 | */ | |
46ce9ded DB |
155 | static int encode_strip(TiffEncoderContext *s, const int8_t *src, |
156 | uint8_t *dst, int n, int compr) | |
716222db | 157 | { |
716222db | 158 | switch (compr) { |
b250f9c6 | 159 | #if CONFIG_ZLIB |
716222db MN |
160 | case TIFF_DEFLATE: |
161 | case TIFF_ADOBE_DEFLATE: | |
46ce9ded DB |
162 | { |
163 | unsigned long zlen = s->buf_size - (*s->buf - s->buf_start); | |
164 | if (compress(dst, &zlen, src, n) != Z_OK) { | |
165 | av_log(s->avctx, AV_LOG_ERROR, "Compressing failed\n"); | |
166 | return -1; | |
716222db | 167 | } |
46ce9ded DB |
168 | return zlen; |
169 | } | |
716222db MN |
170 | #endif |
171 | case TIFF_RAW: | |
172 | if (check_size(s, n)) | |
173 | return -1; | |
174 | memcpy(dst, src, n); | |
175 | return n; | |
176 | case TIFF_PACKBITS: | |
46ce9ded DB |
177 | return ff_rle_encode(dst, s->buf_size - (*s->buf - s->buf_start), |
178 | src, 1, n, 2, 0xff, -1, 0); | |
efd2afc2 MN |
179 | case TIFF_LZW: |
180 | return ff_lzw_encode(s->lzws, src, n); | |
716222db MN |
181 | default: |
182 | return -1; | |
183 | } | |
184 | } | |
185 | ||
f26f7113 AK |
186 | static void pack_yuv(TiffEncoderContext *s, const AVFrame *p, |
187 | uint8_t *dst, int lnum) | |
f4d47d6b | 188 | { |
f4d47d6b | 189 | int i, j, k; |
46ce9ded | 190 | int w = (s->width - 1) / s->subsampling[0] + 1; |
f4d47d6b KN |
191 | uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]]; |
192 | uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]]; | |
46ce9ded | 193 | for (i = 0; i < w; i++) { |
f4d47d6b KN |
194 | for (j = 0; j < s->subsampling[1]; j++) |
195 | for (k = 0; k < s->subsampling[0]; k++) | |
196 | *dst++ = p->data[0][(lnum + j) * p->linesize[0] + | |
197 | i * s->subsampling[0] + k]; | |
198 | *dst++ = *pu++; | |
199 | *dst++ = *pv++; | |
200 | } | |
201 | } | |
202 | ||
46ce9ded | 203 | static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
760b0040 | 204 | const AVFrame *pict, int *got_packet) |
716222db MN |
205 | { |
206 | TiffEncoderContext *s = avctx->priv_data; | |
f26f7113 | 207 | const AVFrame *const p = pict; |
716222db | 208 | int i; |
760b0040 | 209 | uint8_t *ptr; |
716222db MN |
210 | uint8_t *offset; |
211 | uint32_t strips; | |
46ce9ded | 212 | uint32_t *strip_sizes = NULL; |
716222db MN |
213 | uint32_t *strip_offsets = NULL; |
214 | int bytes_per_row; | |
46ce9ded | 215 | uint32_t res[2] = { 72, 1 }; // image resolution (72/1) |
298ed797 | 216 | uint16_t bpp_tab[] = { 8, 8, 8, 8 }; |
62acb493 | 217 | int ret; |
f4d47d6b KN |
218 | int is_yuv = 0; |
219 | uint8_t *yuv_line = NULL; | |
220 | int shift_h, shift_v; | |
49106844 | 221 | int packet_size; |
46ce9ded | 222 | const AVPixFmtDescriptor *pfd; |
716222db | 223 | |
47a1d794 | 224 | s->avctx = avctx; |
716222db | 225 | |
46ce9ded DB |
226 | s->width = avctx->width; |
227 | s->height = avctx->height; | |
f4d47d6b KN |
228 | s->subsampling[0] = 1; |
229 | s->subsampling[1] = 1; | |
716222db MN |
230 | |
231 | switch (avctx->pix_fmt) { | |
716d413c AK |
232 | case AV_PIX_FMT_RGB48LE: |
233 | case AV_PIX_FMT_GRAY16LE: | |
5b1b91cf | 234 | case AV_PIX_FMT_RGBA: |
716d413c AK |
235 | case AV_PIX_FMT_RGB24: |
236 | case AV_PIX_FMT_GRAY8: | |
237 | case AV_PIX_FMT_PAL8: | |
46ce9ded | 238 | pfd = av_pix_fmt_desc_get(avctx->pix_fmt); |
9bc055e3 | 239 | s->bpp = av_get_bits_per_pixel(pfd); |
46ce9ded | 240 | if (pfd->flags & AV_PIX_FMT_FLAG_PAL) |
a9b046fb | 241 | s->photometric_interpretation = TIFF_PHOTOMETRIC_PALETTE; |
46ce9ded | 242 | else if (pfd->flags & AV_PIX_FMT_FLAG_RGB) |
a9b046fb | 243 | s->photometric_interpretation = TIFF_PHOTOMETRIC_RGB; |
46ce9ded | 244 | else |
a9b046fb | 245 | s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO; |
9bc055e3 | 246 | s->bpp_tab_size = pfd->nb_components; |
46ce9ded | 247 | for (i = 0; i < s->bpp_tab_size; i++) |
9bc055e3 | 248 | bpp_tab[i] = s->bpp / s->bpp_tab_size; |
716222db | 249 | break; |
716d413c | 250 | case AV_PIX_FMT_MONOBLACK: |
46ce9ded | 251 | s->bpp = 1; |
a9b046fb | 252 | s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO; |
46ce9ded | 253 | s->bpp_tab_size = 0; |
716222db | 254 | break; |
716d413c | 255 | case AV_PIX_FMT_MONOWHITE: |
46ce9ded | 256 | s->bpp = 1; |
a9b046fb | 257 | s->photometric_interpretation = TIFF_PHOTOMETRIC_WHITE_IS_ZERO; |
46ce9ded | 258 | s->bpp_tab_size = 0; |
716222db | 259 | break; |
716d413c AK |
260 | case AV_PIX_FMT_YUV420P: |
261 | case AV_PIX_FMT_YUV422P: | |
262 | case AV_PIX_FMT_YUV444P: | |
263 | case AV_PIX_FMT_YUV410P: | |
264 | case AV_PIX_FMT_YUV411P: | |
46ce9ded | 265 | av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &shift_h, &shift_v); |
a9b046fb | 266 | s->photometric_interpretation = TIFF_PHOTOMETRIC_YCBCR; |
46ce9ded DB |
267 | s->bpp = 8 + (16 >> (shift_h + shift_v)); |
268 | s->subsampling[0] = 1 << shift_h; | |
269 | s->subsampling[1] = 1 << shift_v; | |
270 | s->bpp_tab_size = 3; | |
271 | is_yuv = 1; | |
f4d47d6b | 272 | break; |
716222db MN |
273 | default: |
274 | av_log(s->avctx, AV_LOG_ERROR, | |
275 | "This colors format is not supported\n"); | |
276 | return -1; | |
277 | } | |
716222db | 278 | |
46ce9ded DB |
279 | if (s->compr == TIFF_DEFLATE || |
280 | s->compr == TIFF_ADOBE_DEFLATE || | |
281 | s->compr == TIFF_LZW) | |
282 | // best choice for DEFLATE | |
716222db MN |
283 | s->rps = s->height; |
284 | else | |
46ce9ded DB |
285 | // suggest size of strip |
286 | s->rps = FFMAX(8192 / (((s->width * s->bpp) >> 3) + 1), 1); | |
287 | // round rps up | |
288 | s->rps = ((s->rps - 1) / s->subsampling[1] + 1) * s->subsampling[1]; | |
716222db MN |
289 | |
290 | strips = (s->height - 1) / s->rps + 1; | |
291 | ||
49106844 TM |
292 | packet_size = avctx->height * ((avctx->width * s->bpp + 7) >> 3) * 2 + |
293 | avctx->height * 4 + FF_MIN_BUFFER_SIZE; | |
294 | ||
760b0040 | 295 | if (!pkt->data && |
49106844 | 296 | (ret = av_new_packet(pkt, packet_size)) < 0) { |
760b0040 AK |
297 | av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); |
298 | return ret; | |
299 | } | |
300 | ptr = pkt->data; | |
301 | s->buf_start = pkt->data; | |
302 | s->buf = &ptr; | |
303 | s->buf_size = pkt->size; | |
304 | ||
716222db MN |
305 | if (check_size(s, 8)) |
306 | goto fail; | |
307 | ||
308 | // write header | |
309 | bytestream_put_le16(&ptr, 0x4949); | |
310 | bytestream_put_le16(&ptr, 42); | |
311 | ||
312 | offset = ptr; | |
313 | bytestream_put_le32(&ptr, 0); | |
314 | ||
46ce9ded | 315 | strip_sizes = av_mallocz(sizeof(*strip_sizes) * strips); |
716222db | 316 | strip_offsets = av_mallocz(sizeof(*strip_offsets) * strips); |
b92dfb56 AC |
317 | if (!strip_sizes || !strip_offsets) { |
318 | ret = AVERROR(ENOMEM); | |
319 | goto fail; | |
320 | } | |
716222db | 321 | |
46ce9ded DB |
322 | bytes_per_row = (((s->width - 1) / s->subsampling[0] + 1) * s->bpp * |
323 | s->subsampling[0] * s->subsampling[1] + 7) >> 3; | |
324 | if (is_yuv) { | |
f4d47d6b | 325 | yuv_line = av_malloc(bytes_per_row); |
46ce9ded | 326 | if (yuv_line == NULL) { |
f4d47d6b | 327 | av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n"); |
b92dfb56 | 328 | ret = AVERROR(ENOMEM); |
f4d47d6b KN |
329 | goto fail; |
330 | } | |
331 | } | |
716222db | 332 | |
b250f9c6 | 333 | #if CONFIG_ZLIB |
716222db MN |
334 | if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { |
335 | uint8_t *zbuf; | |
336 | int zlen, zn; | |
337 | int j; | |
338 | ||
339 | zlen = bytes_per_row * s->rps; | |
340 | zbuf = av_malloc(zlen); | |
b92dfb56 AC |
341 | if (!zbuf) { |
342 | ret = AVERROR(ENOMEM); | |
343 | goto fail; | |
344 | } | |
760b0040 | 345 | strip_offsets[0] = ptr - pkt->data; |
46ce9ded | 346 | zn = 0; |
716222db | 347 | for (j = 0; j < s->rps; j++) { |
46ce9ded | 348 | if (is_yuv) { |
f26f7113 | 349 | pack_yuv(s, p, yuv_line, j); |
f4d47d6b KN |
350 | memcpy(zbuf + zn, yuv_line, bytes_per_row); |
351 | j += s->subsampling[1] - 1; | |
46ce9ded | 352 | } else |
24ba15b1 DB |
353 | memcpy(zbuf + j * bytes_per_row, |
354 | p->data[0] + j * p->linesize[0], bytes_per_row); | |
716222db MN |
355 | zn += bytes_per_row; |
356 | } | |
62acb493 | 357 | ret = encode_strip(s, zbuf, ptr, zn, s->compr); |
716222db | 358 | av_free(zbuf); |
62acb493 | 359 | if (ret < 0) { |
716222db MN |
360 | av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); |
361 | goto fail; | |
362 | } | |
46ce9ded | 363 | ptr += ret; |
760b0040 | 364 | strip_sizes[0] = ptr - pkt->data - strip_offsets[0]; |
716222db MN |
365 | } else |
366 | #endif | |
46ce9ded DB |
367 | if (s->compr == TIFF_LZW) { |
368 | s->lzws = av_malloc(ff_lzw_encode_state_size); | |
369 | if (!s->lzws) { | |
370 | ret = AVERROR(ENOMEM); | |
371 | goto fail; | |
b92dfb56 | 372 | } |
46ce9ded DB |
373 | } |
374 | for (i = 0; i < s->height; i++) { | |
375 | if (strip_sizes[i / s->rps] == 0) { | |
376 | if (s->compr == TIFF_LZW) { | |
377 | ff_lzw_encode_init(s->lzws, ptr, | |
378 | s->buf_size - (*s->buf - s->buf_start), | |
379 | 12, FF_LZW_TIFF, put_bits); | |
efd2afc2 | 380 | } |
46ce9ded DB |
381 | strip_offsets[i / s->rps] = ptr - pkt->data; |
382 | } | |
383 | if (is_yuv) { | |
f26f7113 | 384 | pack_yuv(s, p, yuv_line, i); |
46ce9ded DB |
385 | ret = encode_strip(s, yuv_line, ptr, bytes_per_row, s->compr); |
386 | i += s->subsampling[1] - 1; | |
387 | } else | |
388 | ret = encode_strip(s, p->data[0] + i * p->linesize[0], | |
389 | ptr, bytes_per_row, s->compr); | |
390 | if (ret < 0) { | |
391 | av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); | |
392 | goto fail; | |
393 | } | |
394 | strip_sizes[i / s->rps] += ret; | |
395 | ptr += ret; | |
396 | if (s->compr == TIFF_LZW && | |
397 | (i == s->height - 1 || i % s->rps == s->rps - 1)) { | |
398 | ret = ff_lzw_encode_flush(s->lzws, flush_put_bits); | |
399 | strip_sizes[(i / s->rps)] += ret; | |
400 | ptr += ret; | |
716222db MN |
401 | } |
402 | } | |
46ce9ded DB |
403 | if (s->compr == TIFF_LZW) |
404 | av_free(s->lzws); | |
716222db MN |
405 | |
406 | s->num_entries = 0; | |
407 | ||
46ce9ded DB |
408 | add_entry1(s, TIFF_SUBFILE, TIFF_LONG, 0); |
409 | add_entry1(s, TIFF_WIDTH, TIFF_LONG, s->width); | |
410 | add_entry1(s, TIFF_HEIGHT, TIFF_LONG, s->height); | |
716222db MN |
411 | |
412 | if (s->bpp_tab_size) | |
46ce9ded | 413 | add_entry(s, TIFF_BPP, TIFF_SHORT, s->bpp_tab_size, bpp_tab); |
716222db | 414 | |
a9b046fb JR |
415 | add_entry1(s, TIFF_COMPR, TIFF_SHORT, s->compr); |
416 | add_entry1(s, TIFF_PHOTOMETRIC, TIFF_SHORT, s->photometric_interpretation); | |
417 | add_entry(s, TIFF_STRIP_OFFS, TIFF_LONG, strips, strip_offsets); | |
716222db MN |
418 | |
419 | if (s->bpp_tab_size) | |
46ce9ded | 420 | add_entry1(s, TIFF_SAMPLES_PER_PIXEL, TIFF_SHORT, s->bpp_tab_size); |
716222db | 421 | |
46ce9ded DB |
422 | add_entry1(s, TIFF_ROWSPERSTRIP, TIFF_LONG, s->rps); |
423 | add_entry(s, TIFF_STRIP_SIZE, TIFF_LONG, strips, strip_sizes); | |
424 | add_entry(s, TIFF_XRES, TIFF_RATIONAL, 1, res); | |
425 | add_entry(s, TIFF_YRES, TIFF_RATIONAL, 1, res); | |
426 | add_entry1(s, TIFF_RES_UNIT, TIFF_SHORT, 2); | |
c28baf06 | 427 | |
46ce9ded DB |
428 | if (!(avctx->flags & CODEC_FLAG_BITEXACT)) |
429 | add_entry(s, TIFF_SOFTWARE_NAME, TIFF_STRING, | |
430 | strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT); | |
716222db | 431 | |
716d413c | 432 | if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { |
716222db MN |
433 | uint16_t pal[256 * 3]; |
434 | for (i = 0; i < 256; i++) { | |
435 | uint32_t rgb = *(uint32_t *) (p->data[1] + i * 4); | |
436 | pal[i] = ((rgb >> 16) & 0xff) * 257; | |
46ce9ded DB |
437 | pal[i + 256] = ((rgb >> 8) & 0xff) * 257; |
438 | pal[i + 512] = (rgb & 0xff) * 257; | |
716222db MN |
439 | } |
440 | add_entry(s, TIFF_PAL, TIFF_SHORT, 256 * 3, pal); | |
441 | } | |
46ce9ded | 442 | if (is_yuv) { |
f4d47d6b | 443 | /** according to CCIR Recommendation 601.1 */ |
46ce9ded | 444 | uint32_t refbw[12] = { 15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1 }; |
f4d47d6b KN |
445 | add_entry(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT, 2, s->subsampling); |
446 | add_entry(s, TIFF_REFERENCE_BW, TIFF_RATIONAL, 6, refbw); | |
447 | } | |
46ce9ded DB |
448 | // write offset to dir |
449 | bytestream_put_le32(&offset, ptr - pkt->data); | |
716222db | 450 | |
62acb493 AK |
451 | if (check_size(s, 6 + s->num_entries * 12)) { |
452 | ret = AVERROR(EINVAL); | |
716222db | 453 | goto fail; |
62acb493 | 454 | } |
716222db MN |
455 | bytestream_put_le16(&ptr, s->num_entries); // write tag count |
456 | bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12); | |
457 | bytestream_put_le32(&ptr, 0); | |
458 | ||
760b0040 AK |
459 | pkt->size = ptr - pkt->data; |
460 | pkt->flags |= AV_PKT_FLAG_KEY; | |
461 | *got_packet = 1; | |
716222db MN |
462 | |
463 | fail: | |
464 | av_free(strip_sizes); | |
465 | av_free(strip_offsets); | |
f4d47d6b | 466 | av_free(yuv_line); |
716222db MN |
467 | return ret; |
468 | } | |
469 | ||
f26f7113 AK |
470 | static av_cold int encode_init(AVCodecContext *avctx) |
471 | { | |
472 | avctx->coded_frame = av_frame_alloc(); | |
473 | if (!avctx->coded_frame) | |
474 | return AVERROR(ENOMEM); | |
475 | ||
476 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; | |
477 | avctx->coded_frame->key_frame = 1; | |
478 | ||
479 | return 0; | |
480 | } | |
481 | ||
482 | static av_cold int encode_close(AVCodecContext *avctx) | |
483 | { | |
484 | av_frame_free(&avctx->coded_frame); | |
485 | return 0; | |
486 | } | |
487 | ||
a94c769d AK |
488 | #define OFFSET(x) offsetof(TiffEncoderContext, x) |
489 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |
490 | static const AVOption options[] = { | |
46ce9ded DB |
491 | { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, { .i64 = TIFF_PACKBITS }, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" }, |
492 | { "packbits", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_PACKBITS }, 0, 0, VE, "compression_algo" }, | |
493 | { "raw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_RAW }, 0, 0, VE, "compression_algo" }, | |
494 | { "lzw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_LZW }, 0, 0, VE, "compression_algo" }, | |
a94c769d | 495 | #if CONFIG_ZLIB |
46ce9ded | 496 | { "deflate", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TIFF_DEFLATE }, 0, 0, VE, "compression_algo" }, |
a94c769d AK |
497 | #endif |
498 | { NULL }, | |
499 | }; | |
500 | ||
501 | static const AVClass tiffenc_class = { | |
502 | .class_name = "TIFF encoder", | |
503 | .item_name = av_default_item_name, | |
504 | .option = options, | |
505 | .version = LIBAVUTIL_VERSION_INT, | |
506 | }; | |
507 | ||
d36beb3f | 508 | AVCodec ff_tiff_encoder = { |
ec6402b7 | 509 | .name = "tiff", |
46ce9ded | 510 | .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), |
ec6402b7 | 511 | .type = AVMEDIA_TYPE_VIDEO, |
36ef5369 | 512 | .id = AV_CODEC_ID_TIFF, |
ec6402b7 | 513 | .priv_data_size = sizeof(TiffEncoderContext), |
f26f7113 AK |
514 | .init = encode_init, |
515 | .close = encode_close, | |
760b0040 | 516 | .encode2 = encode_frame, |
716d413c AK |
517 | .pix_fmts = (const enum AVPixelFormat[]) { |
518 | AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8, | |
5b1b91cf | 519 | AV_PIX_FMT_RGBA, |
716d413c AK |
520 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16LE, |
521 | AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_MONOWHITE, | |
522 | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, | |
523 | AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, | |
524 | AV_PIX_FMT_NONE | |
14285275 | 525 | }, |
a94c769d | 526 | .priv_class = &tiffenc_class, |
716222db | 527 | }; |