}
}
+static void av_always_inline split_nibbles(uint8_t *dst, const uint8_t *src,
+ int width)
+{
+ while (--width >= 0) {
+ // src == dst for LZW
+ dst[width * 2 + 1] = src[width] & 0xF;
+ dst[width * 2 + 0] = src[width] >> 4;
+ }
+}
+
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;
}
src = zbuf;
for(line = 0; line < lines; line++){
- memcpy(dst, src, width);
+ if(s->bpp == 4){
+ split_nibbles(dst, src, width);
+ }else{
+ memcpy(dst, src, width);
+ }
dst += stride;
src += width;
}
}
switch(s->compr){
case TIFF_RAW:
+ if (ssrc + size - src < width)
+ return AVERROR_INVALIDDATA;
if (!s->fill_order) {
horizontal_fill(s->bpp, dst, 1, src, 0, width, 0);
} else {
av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", pixels, width);
return -1;
}
+ if(s->bpp == 4)
+ split_nibbles(dst, dst, width);
break;
}
dst += stride;
/* make default grayscale pal */
pal = (uint32_t *) s->picture.data[1];
for (i = 0; i < 1<<s->bpp; i++)
- pal[i] = i * 255 / ((1<<s->bpp) - 1) * 0x010101;
+ pal[i] = 0xFF << 24 | i * 255 / ((1<<s->bpp) - 1) * 0x010101;
}
}
return 0;
uint32_t *pal;
const uint8_t *rp, *gp, *bp;
+ if (end_buf - buf < 12)
+ return -1;
tag = tget_short(&buf, s->le);
type = tget_short(&buf, s->le);
count = tget_long(&buf, s->le);
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 && buf < end_buf; i++) s->bpp += tget(&buf, type, s->le);
break;
default:
s->bpp = -1;
case TIFF_PAL:
pal = (uint32_t *) s->palette;
off = type_sizes[type];
+ if (count / 3 > 256 || end_buf - buf < count / 3 * off * 3)
+ return -1;
rp = buf;
gp = buf + count / 3 * off;
bp = buf + count / 3 * off * 2;
AVFrame *picture = data;
AVFrame * const p= (AVFrame*)&s->picture;
const uint8_t *orig_buf = buf, *end_buf = buf + buf_size;
- int id, le, off, ret;
+ unsigned off;
+ int id, le, ret;
int i, j, entries;
- int stride, soff, ssize;
+ int stride;
+ unsigned soff, ssize;
uint8_t *dst;
//parse image header
+ if (end_buf - buf < 8)
+ return AVERROR_INVALIDDATA;
id = AV_RL16(buf); buf += 2;
if(id == 0x4949) le = 1;
else if(id == 0x4D4D) le = 0;
}
/* parse image file directory */
off = tget_long(&buf, le);
- if(orig_buf + off + 14 >= end_buf){
+ if (off >= UINT_MAX - 14 || end_buf - orig_buf < off + 14) {
av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
buf = orig_buf + off;
entries = tget_short(&buf, le);
stride = p->linesize[0];
dst = p->data[0];
for(i = 0; i < s->height; i += s->rps){
- if(s->stripsizes)
+ if(s->stripsizes) {
+ if (s->stripsizes >= end_buf)
+ return AVERROR_INVALIDDATA;
ssize = tget(&s->stripsizes, s->sstype, s->le);
- else
+ } else
ssize = s->stripsize;
- if (ssize > buf_size) {
- av_log(avctx, AV_LOG_ERROR, "Buffer size is smaller than strip size\n");
- return -1;
- }
-
if(s->stripdata){
+ if (s->stripdata >= end_buf)
+ return AVERROR_INVALIDDATA;
soff = tget(&s->stripdata, s->sot, s->le);
}else
soff = s->stripoff;
- if (soff < 0) {
- av_log(avctx, AV_LOG_ERROR, "Invalid stripoff: %d\n", soff);
- return AVERROR(EINVAL);
+
+ if (soff > buf_size || ssize > buf_size - soff) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n");
+ return -1;
}
if(tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize, FFMIN(s->rps, s->height - i)) < 0)
break;
dst = p->data[0];
soff = s->bpp >> 3;
ssize = s->width * soff;
- for(i = 0; i < s->height; i++) {
- for(j = soff; j < ssize; j++)
- dst[j] += dst[j - soff];
- dst += stride;
+ if (s->avctx->pix_fmt == PIX_FMT_RGB48LE) {
+ for (i = 0; i < s->height; i++) {
+ for (j = soff; j < ssize; j += 2)
+ AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff));
+ dst += stride;
+ }
+ } else if (s->avctx->pix_fmt == PIX_FMT_RGB48BE) {
+ for (i = 0; i < s->height; i++) {
+ for (j = soff; j < ssize; j += 2)
+ AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff));
+ dst += stride;
+ }
+ } else {
+ for(i = 0; i < s->height; i++) {
+ for(j = soff; j < ssize; j++)
+ dst[j] += dst[j - soff];
+ dst += stride;
+ }
}
}
if(s->invert){
- uint8_t *src;
- int j;
-
- src = s->picture.data[0];
- for(j = 0; j < s->height; j++){
- for(i = 0; i < s->picture.linesize[0]; i++)
- src[i] = (s->avctx->pix_fmt == PIX_FMT_PAL8 ? (1<<s->bpp) - 1 : 255) - src[i];
- src += s->picture.linesize[0];
+ dst = s->picture.data[0];
+ for(i = 0; i < s->height; i++){
+ for(j = 0; j < s->picture.linesize[0]; j++)
+ dst[j] = (s->avctx->pix_fmt == PIX_FMT_PAL8 ? (1<<s->bpp) - 1 : 255) - dst[j];
+ dst += s->picture.linesize[0];
}
}
*picture= *(AVFrame*)&s->picture;