Commit bbc572a2 authored by Stefano Sabatini's avatar Stefano Sabatini Committed by Diego Biurrun

tiff: add support for SamplesPerPixel tag in tiff_decode_tag()

Format detection and internal frame initialization is moved to a
separate init_image() function, which is called when all the tags have
been read, and so both BitsPerSample and SamplesPerPixel information
has been collected.

This fixes decoding of the file 11.tiff from roundup issue #1925.

Based on a patch by Kostya Shishkov <kostya.shishkov@gmail.com>.
Signed-off-by: 's avatarDiego Biurrun <diego@biurrun.de>
parent 8102d886
...@@ -40,7 +40,7 @@ typedef struct TiffContext { ...@@ -40,7 +40,7 @@ typedef struct TiffContext {
AVFrame picture; AVFrame picture;
int width, height; int width, height;
unsigned int bpp; unsigned int bpp, bppcount;
int le; int le;
enum TiffCompr compr; enum TiffCompr compr;
int invert; int invert;
...@@ -216,6 +216,55 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin ...@@ -216,6 +216,55 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin
return 0; return 0;
} }
static int init_image(TiffContext *s)
{
int i, ret;
uint32_t *pal;
switch (s->bpp * 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->bpp, 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->bpp == 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) static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *buf, const uint8_t *end_buf)
{ {
...@@ -269,6 +318,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * ...@@ -269,6 +318,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
s->height = value; s->height = value;
break; break;
case TIFF_BPP: case TIFF_BPP:
s->bppcount = count;
if(count > 4){ 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, "This format is not supported (bpp=%d, %d components)\n", s->bpp, count);
return -1; return -1;
...@@ -288,46 +338,16 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * ...@@ -288,46 +338,16 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *
s->bpp = -1; s->bpp = -1;
} }
} }
switch(s->bpp*10 + count){ break;
case 11: case TIFF_SAMPLES_PER_PIXEL:
s->avctx->pix_fmt = PIX_FMT_MONOBLACK; if (count != 1) {
break; av_log(s->avctx, AV_LOG_ERROR,
case 81: "Samples per pixel requires a single value, many provided\n");
s->avctx->pix_fmt = PIX_FMT_PAL8; return AVERROR_INVALIDDATA;
break; }
case 243: if (s->bppcount == 1)
s->avctx->pix_fmt = PIX_FMT_RGB24; s->bpp *= value;
break; s->bppcount = value;
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; break;
case TIFF_COMPR: case TIFF_COMPR:
s->compr = value; s->compr = value;
...@@ -469,7 +489,7 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -469,7 +489,7 @@ static int decode_frame(AVCodecContext *avctx,
AVFrame *picture = data; AVFrame *picture = data;
AVFrame * const p= (AVFrame*)&s->picture; AVFrame * const p= (AVFrame*)&s->picture;
const uint8_t *orig_buf = buf, *end_buf = buf + buf_size; 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 i, j, entries;
int stride, soff, ssize; int stride, soff, ssize;
uint8_t *dst; uint8_t *dst;
...@@ -510,21 +530,9 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -510,21 +530,9 @@ static int decode_frame(AVCodecContext *avctx,
return -1; return -1;
} }
/* now we have the data and may start decoding */ /* now we have the data and may start decoding */
if(!p->data[0]){ if ((ret = init_image(s)) < 0)
s->bpp = 1; return ret;
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(s->strips == 1 && !s->stripsize){ if(s->strips == 1 && !s->stripsize){
av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); av_log(avctx, AV_LOG_WARNING, "Image data size missing\n");
s->stripsize = buf_size - s->stripoff; s->stripsize = buf_size - s->stripoff;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment