diff options
author | Paul B Mahol <onemda@gmail.com> | 2017-02-21 12:17:21 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2017-02-21 12:17:21 +0100 |
commit | f4777d1b89c65166394a459399704fc034a782d6 (patch) | |
tree | a3dff0b3ed1859a300359244af0c83e425aa9e6e | |
parent | 74267333a10e0be4355221d7be22dab73bd7184c (diff) | |
download | ffmpeg-f4777d1b89c65166394a459399704fc034a782d6.tar.gz |
avcodec/qdrw: add support for decoding rgb555
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r-- | libavcodec/qdrw.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index 65914fae84..34b97dc9aa 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -68,6 +68,57 @@ static int parse_palette(AVCodecContext *avctx, GetByteContext *gbc, return 0; } +static int decode_rle16(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc) +{ + int offset = avctx->width * 2; + uint8_t *outdata = p->data[0]; + int i, j; + + for (i = 0; i < avctx->height; i++) { + int size, left, code, pix; + uint16_t *out = (uint16_t *)outdata; + int pos = 0; + + /* size of packed line */ + size = left = bytestream2_get_be16(gbc); + if (bytestream2_get_bytes_left(gbc) < size) + return AVERROR_INVALIDDATA; + + /* decode line */ + while (left > 0) { + code = bytestream2_get_byte(gbc); + if (code & 0x80 ) { /* run */ + pix = bytestream2_get_be16(gbc); + for (j = 0; j < 257 - code; j++) { + out[pos] = pix; + pos++; + if (pos >= offset) { + pos -= offset; + pos++; + } + if (pos >= offset) + return AVERROR_INVALIDDATA; + } + left -= 3; + } else { /* copy */ + for (j = 0; j < code + 1; j++) { + out[pos] = bytestream2_get_be16(gbc); + pos++; + if (pos >= offset) { + pos -= offset; + pos++; + } + if (pos >= offset) + return AVERROR_INVALIDDATA; + } + left -= 1 + (code + 1) * 2; + } + } + outdata += p->linesize[0]; + } + return 0; +} + static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc, int step) { @@ -205,6 +256,8 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); if (bppcnt == 1 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else if (bppcnt == 3 && bpp == 5) { + avctx->pix_fmt = AV_PIX_FMT_RGB555; } else { av_log(avctx, AV_LOG_ERROR, "Invalid pixel format (bppcnt %d bpp %d) in Packbit\n", @@ -240,7 +293,10 @@ static int decode_frame(AVCodecContext *avctx, avpriv_report_missing_feature(avctx, "Packbit mask region"); } - ret = decode_rle(avctx, p, &gbc, bppcnt); + if (avctx->pix_fmt == AV_PIX_FMT_RGB555) + ret = decode_rle16(avctx, p, &gbc); + else + ret = decode_rle(avctx, p, &gbc, bppcnt); if (ret < 0) return ret; *got_frame = 1; @@ -266,6 +322,8 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); if (bppcnt == 3 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else if (bppcnt == 3 && bpp == 5) { + avctx->pix_fmt = AV_PIX_FMT_RGB555; } else if (bppcnt == 4 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_ARGB; } else { @@ -294,7 +352,10 @@ static int decode_frame(AVCodecContext *avctx, avpriv_report_missing_feature(avctx, "DirectBit mask region"); } - ret = decode_rle(avctx, p, &gbc, bppcnt); + if (avctx->pix_fmt == AV_PIX_FMT_RGB555) + ret = decode_rle16(avctx, p, &gbc); + else + ret = decode_rle(avctx, p, &gbc, bppcnt); if (ret < 0) return ret; *got_frame = 1; |