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