[FFmpeg-devel] [PATCH] tiff: add support to TIFF_SAMPLES_PER_PIXEL case in tiff_decode_tag()
Stefano Sabatini
stefano.sabatini-lala at poste.it
Mon May 9 22:27:44 CEST 2011
Also add support for bits per component storage.
Fix decoding of file 11.tiff, trac issue number #167.
Based on a patch by Kostya Shiskov <kostya.shishkov at gmail.com>.
---
libavcodec/tiff.c | 139 ++++++++++++++++++++++++++++-------------------------
1 files changed, 74 insertions(+), 65 deletions(-)
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index f252913..cdf8ccd 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -38,7 +38,7 @@ typedef struct TiffContext {
AVFrame picture;
int width, height;
- unsigned int bpp;
+ unsigned int bpp[4], bppcount, totalbpp;
int le;
enum TiffCompr compr;
int invert;
@@ -101,7 +101,7 @@ static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src,
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;
- int width = s->width * s->bpp >> 3;
+ int width = s->width * s->totalbpp >> 3;
#if CONFIG_ZLIB
uint8_t *zbuf; unsigned long outlen;
@@ -208,6 +208,58 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin
return 0;
}
+static int init_image(TiffContext *s)
+{
+ int i, ret;
+ uint32_t *pal;
+
+ /* compute total bpp */
+ s->totalbpp = 0;
+ for (i = 0; i < s->bppcount; i++)
+ s->totalbpp += s->bpp[i] ? s->bpp[i] : s->bpp[0];
+
+ switch (s->totalbpp*10 + s->bppcount) {
+ case 11:
+ s->avctx->pix_fmt = PIX_FMT_MONOBLACK;
+ break;
+ case 81:
+ s->avctx->pix_fmt = PIX_FMT_PAL8;
+ break;
+ case 243:
+ s->avctx->pix_fmt = PIX_FMT_RGB24;
+ break;
+ case 161:
+ s->avctx->pix_fmt = PIX_FMT_GRAY16BE;
+ break;
+ case 324:
+ s->avctx->pix_fmt = PIX_FMT_RGBA;
+ break;
+ case 483:
+ s->avctx->pix_fmt = s->le ? PIX_FMT_RGB48LE : PIX_FMT_RGB48BE;
+ break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, bppcount=%d)\n", s->totalbpp, s->bppcount);
+ return AVERROR_INVALIDDATA;
+ }
+ if (s->width != s->avctx->width || s->height != s->avctx->height) {
+ if ((ret = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0)
+ return ret;
+ avcodec_set_dimensions(s->avctx, s->width, s->height);
+ }
+ if (s->picture.data[0])
+ s->avctx->release_buffer(s->avctx, &s->picture);
+ if ((ret = s->avctx->get_buffer(s->avctx, &s->picture)) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ if (s->totalbpp == 8 && s->picture.data[1]){
+ /* make default grayscale pal */
+ pal = (uint32_t *) s->picture.data[1];
+ for (i = 0; i < 256; i++)
+ pal[i] = i * 0x010101;
+ }
+ return 0;
+}
static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *buf, const uint8_t *end_buf)
{
@@ -261,65 +313,33 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
s->height = value;
break;
case TIFF_BPP:
+ s->bppcount = count;
if(count > 4){
- av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", s->bpp, count);
+ av_log(s->avctx, AV_LOG_ERROR, "More than 4 pixel components are not supported, %d specified\n", count);
return -1;
}
- if(count == 1) s->bpp = value;
+ if (count == 1) s->bpp[0] = value;
else{
switch(type){
case TIFF_BYTE:
- s->bpp = (off & 0xFF) + ((off >> 8) & 0xFF) + ((off >> 16) & 0xFF) + ((off >> 24) & 0xFF);
+ s->bpp[0] = off & 0xFF;
+ s->bpp[1] = (off >> 8) & 0xFF;
+ s->bpp[2] = (off >> 16) & 0xFF;
+ s->bpp[3] = (off >> 24) & 0xFF;
break;
case TIFF_SHORT:
case TIFF_LONG:
- s->bpp = 0;
- for(i = 0; i < count; i++) s->bpp += tget(&buf, type, s->le);
+ for (i = 0; i < count; i++) s->bpp[i] = tget(&buf, type, s->le);
break;
- default:
- s->bpp = -1;
}
}
- switch(s->bpp*10 + count){
- case 11:
- s->avctx->pix_fmt = PIX_FMT_MONOBLACK;
- break;
- case 81:
- s->avctx->pix_fmt = PIX_FMT_PAL8;
- break;
- case 243:
- s->avctx->pix_fmt = PIX_FMT_RGB24;
- break;
- case 161:
- s->avctx->pix_fmt = PIX_FMT_GRAY16BE;
- break;
- case 324:
- s->avctx->pix_fmt = PIX_FMT_RGBA;
- break;
- case 483:
- s->avctx->pix_fmt = s->le ? PIX_FMT_RGB48LE : PIX_FMT_RGB48BE;
- break;
- default:
- av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", s->bpp, count);
- return -1;
- }
- if(s->width != s->avctx->width || s->height != s->avctx->height){
- if(av_image_check_size(s->width, s->height, 0, s->avctx))
- 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->bpp == 8){
- /* make default grayscale pal */
- pal = (uint32_t *) s->picture.data[1];
- for(i = 0; i < 256; i++)
- pal[i] = i * 0x010101;
+ break;
+ case TIFF_SAMPLES_PER_PIXEL:
+ if (count != 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "Samples per pixel is not a single value\n");
+ return AVERROR_INVALIDDATA;
}
+ s->bppcount = value;
break;
case TIFF_COMPR:
s->compr = value;
@@ -462,7 +482,7 @@ static int decode_frame(AVCodecContext *avctx,
AVFrame *picture = data;
AVFrame * const p= (AVFrame*)&s->picture;
const uint8_t *orig_buf = buf, *end_buf = buf + buf_size;
- int id, le, off;
+ int id, le, off, ret;
int i, j, entries;
int stride, soff, ssize;
uint8_t *dst;
@@ -502,22 +522,11 @@ static int decode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "Image data is missing\n");
return -1;
}
+
/* now we have the data and may start decoding */
- if(!p->data[0]){
- s->bpp = 1;
- avctx->pix_fmt = PIX_FMT_MONOBLACK;
- if(s->width != s->avctx->width || s->height != s->avctx->height){
- if(av_image_check_size(s->width, s->height, 0, s->avctx))
- 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 ((ret = init_image(s)) < 0)
+ return ret;
+
if(s->strips == 1 && !s->stripsize){
av_log(avctx, AV_LOG_WARNING, "Image data size missing\n");
s->stripsize = buf_size - s->stripoff;
@@ -549,7 +558,7 @@ static int decode_frame(AVCodecContext *avctx,
}
if(s->predictor == 2){
dst = p->data[0];
- soff = s->bpp >> 3;
+ soff = s->totalbpp >> 3;
ssize = s->width * soff;
for(i = 0; i < s->height; i++) {
for(j = soff; j < ssize; j++)
--
1.7.2.3
More information about the ffmpeg-devel
mailing list