mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
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: Diego Biurrun <diego@biurrun.de>
This commit is contained in:
parent
8102d886be
commit
bbc572a2c4
@ -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
|
|||||||
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 *
|
|||||||
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 *
|
|||||||
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:
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
if (s->bppcount == 1)
|
||||||
|
s->bpp *= value;
|
||||||
|
s->bppcount = value;
|
||||||
break;
|
break;
|
||||||
case TIFF_COMPR:
|
case TIFF_COMPR:
|
||||||
s->compr = value;
|
s->compr = value;
|
||||||
@ -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,
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user