X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Ftiff.c;h=8818a665307e34b5ccd1528781ce2965a1fd11a3;hb=b07781b6e4f6267f20aec4e7f1d390ddb223af46;hp=b7f4db31704c8427c3758a9ff202cadc9fde551b;hpb=9706d1c766b609961bea44d475c84c01b7ee10a5;p=ffmpeg diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index b7f4db31704..8818a665307 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -44,6 +44,7 @@ typedef struct TiffContext { int invert; int fax_opts; int predictor; + int fill_order; int strips, rps, sstype; int sot; @@ -74,6 +75,29 @@ static int tget(const uint8_t **p, int type, int le){ } } +#if CONFIG_ZLIB +static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, int size) +{ + z_stream zstream; + int zret; + + memset(&zstream, 0, sizeof(zstream)); + zstream.next_in = src; + zstream.avail_in = size; + zstream.next_out = dst; + zstream.avail_out = *len; + zret = inflateInit(&zstream); + if (zret != Z_OK) { + av_log(NULL, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return zret; + } + zret = inflate(&zstream, Z_SYNC_FLUSH); + inflateEnd(&zstream); + *len = zstream.total_out; + return zret == Z_STREAM_END ? Z_OK : zret; +} +#endif + static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uint8_t *src, int size, int lines){ int c, line, pixels, code; const uint8_t *ssrc = src; @@ -82,10 +106,12 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin uint8_t *zbuf; unsigned long outlen; if(s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE){ + int ret; outlen = width * lines; zbuf = av_malloc(outlen); - if(uncompress(zbuf, &outlen, src, size) != Z_OK){ - av_log(s->avctx, AV_LOG_ERROR, "Uncompressing failed (%lu of %lu)\n", outlen, (unsigned long)width * lines); + ret = tiff_uncompress(zbuf, &outlen, src, size); + if(ret != Z_OK){ + av_log(s->avctx, AV_LOG_ERROR, "Uncompressing failed (%lu of %lu) with error %d\n", outlen, (unsigned long)width * lines, ret); av_free(zbuf); return -1; } @@ -113,16 +139,23 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); return -1; } - for(i = 0; i < size; i++) - src2[i] = ff_reverse[src[i]]; + if(s->fax_opts & 2){ + av_log(s->avctx, AV_LOG_ERROR, "Uncompressed fax mode is not supported (yet)\n"); + av_free(src2); + return -1; + } + if(!s->fill_order){ + memcpy(src2, src, size); + }else{ + for(i = 0; i < size; i++) + src2[i] = ff_reverse[src[i]]; + } memset(src2+size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - if(s->compr == TIFF_G3 && !(s->fax_opts & 1)) - s->compr = TIFF_CCITT_RLE; switch(s->compr){ case TIFF_CCITT_RLE: case TIFF_G3: case TIFF_G4: - ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, s->compr); + ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, s->compr, s->fax_opts); break; } av_free(src2); @@ -375,6 +408,13 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * return -1; } break; + case TIFF_FILL_ORDER: + if(value < 1 || value > 2){ + av_log(s->avctx, AV_LOG_ERROR, "Unknown FillOrder value %d, trying default one\n", value); + value = 1; + } + s->fill_order = value - 1; + break; case TIFF_PAL: if(s->avctx->pix_fmt != PIX_FMT_PAL8){ av_log(s->avctx, AV_LOG_ERROR, "Palette met but this is not palettized format\n"); @@ -400,8 +440,12 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * } break; case TIFF_T4OPTIONS: + if(s->compr == TIFF_G3) + s->fax_opts = value; + break; case TIFF_T6OPTIONS: - s->fax_opts = value; + if(s->compr == TIFF_G4) + s->fax_opts = value; break; } return 0; @@ -433,6 +477,7 @@ static int decode_frame(AVCodecContext *avctx, s->le = le; s->invert = 0; s->compr = TIFF_RAW; + s->fill_order = 0; // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number // that further identifies the file as a TIFF file" if(tget_short(&buf, le) != 42){ @@ -458,8 +503,19 @@ static int decode_frame(AVCodecContext *avctx, } /* now we have the data and may start decoding */ if(!p->data[0]){ - av_log(s->avctx, AV_LOG_ERROR, "Picture initialization missing\n"); - return -1; + s->bpp = 1; + avctx->pix_fmt = PIX_FMT_MONOBLACK; + if(s->width != s->avctx->width || s->height != s->avctx->height){ + if(avcodec_check_dimensions(s->avctx, s->width, s->height)) + return -1; + avcodec_set_dimensions(s->avctx, s->width, s->height); + } + if(s->picture.data[0]) + s->avctx->release_buffer(s->avctx, &s->picture); + if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){ + av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } } if(s->strips == 1 && !s->stripsize){ av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); @@ -542,7 +598,7 @@ AVCodec tiff_decoder = { NULL, tiff_end, decode_frame, - 0, + CODEC_CAP_DR1, NULL, .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), };