diff options
Diffstat (limited to 'libavcodec/sunrast.c')
-rw-r--r-- | libavcodec/sunrast.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/libavcodec/sunrast.c b/libavcodec/sunrast.c index 281913fd58..1e25b6011f 100644 --- a/libavcodec/sunrast.c +++ b/libavcodec/sunrast.c @@ -2,20 +2,20 @@ * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder * Copyright (c) 2007, 2008 Ivo van Poorten * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -33,7 +33,7 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, const uint8_t *buf_end = avpkt->data + avpkt->size; AVFrame * const p = data; unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen; - uint8_t *ptr; + uint8_t *ptr, *ptr2 = NULL; const uint8_t *bufstart = buf; int ret; @@ -53,7 +53,7 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, maplength = AV_RB32(buf + 28); buf += 32; - if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF || type == RT_EXPERIMENTAL) { + if (type == RT_EXPERIMENTAL) { avpriv_request_sample(avctx, "TIFF/IFF/EXPERIMENTAL (compression) type"); return AVERROR_PATCHWELCOME; } @@ -74,10 +74,17 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } + if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) { + av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n"); + return -1; + } switch (depth) { case 1: - avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_MONOWHITE; + break; + case 4: + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_NONE; break; case 8: avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; @@ -85,6 +92,9 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, case 24: avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24; break; + case 32: + avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_0RGB : AV_PIX_FMT_0BGR; + break; default: av_log(avctx, AV_LOG_ERROR, "invalid depth\n"); return AVERROR_INVALIDDATA; @@ -92,17 +102,15 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, if (w != avctx->width || h != avctx->height) avcodec_set_dimensions(avctx, w, h); - if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - } p->pict_type = AV_PICTURE_TYPE_I; if (buf_end - buf < maplength) return AVERROR_INVALIDDATA; - if (depth != 8 && maplength) { + if (depth > 8 && maplength) { av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n"); } else if (maplength) { @@ -115,13 +123,20 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, ptr = p->data[1]; for (x = 0; x < len; x++, ptr += 4) - *(uint32_t *)ptr = (buf[x] << 16) + (buf[len + x] << 8) + buf[len + len + x]; + *(uint32_t *)ptr = (0xFFU<<24) + (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x]; } buf += maplength; + if (maplength && depth < 8) { + ptr = ptr2 = av_malloc((w + 15) * h); + if (!ptr) + return AVERROR(ENOMEM); + stride = (w + 15 >> 3) * depth; + } else { ptr = p->data[0]; stride = p->linesize[0]; + } /* scanlines are aligned on 16 bit boundaries */ len = (depth * w + 7) >> 3; @@ -162,6 +177,30 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, buf += alen; } } + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && depth < 8) { + uint8_t *ptr_free = ptr2; + ptr = p->data[0]; + for (y=0; y<h; y++) { + for (x = 0; x < (w + 7 >> 3) * depth; x++) { + if (depth == 1) { + ptr[8*x] = ptr2[x] >> 7; + ptr[8*x+1] = ptr2[x] >> 6 & 1; + ptr[8*x+2] = ptr2[x] >> 5 & 1; + ptr[8*x+3] = ptr2[x] >> 4 & 1; + ptr[8*x+4] = ptr2[x] >> 3 & 1; + ptr[8*x+5] = ptr2[x] >> 2 & 1; + ptr[8*x+6] = ptr2[x] >> 1 & 1; + ptr[8*x+7] = ptr2[x] & 1; + } else { + ptr[2*x] = ptr2[x] >> 4; + ptr[2*x+1] = ptr2[x] & 0xF; + } + } + ptr += p->linesize[0]; + ptr2 += (w + 15 >> 3) * depth; + } + av_freep(&ptr_free); + } *got_frame = 1; |