diff options
Diffstat (limited to 'libavcodec/bmp.c')
-rw-r--r-- | libavcodec/bmp.c | 73 |
1 files changed, 31 insertions, 42 deletions
diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index 899fc8a..a3bb1a7 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -2,20 +2,20 @@ * BMP image format decoder * Copyright (c) 2005 Mans Rullgard * - * 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 */ @@ -38,7 +38,8 @@ static int bmp_decode_frame(AVCodecContext *avctx, BiCompression comp; unsigned int ihsize; int i, j, n, linesize, ret; - uint32_t rgb[3]; + uint32_t rgb[3] = {0}; + uint32_t alpha = 0; uint8_t *ptr; int dsize; const uint8_t *buf0 = buf; @@ -83,7 +84,8 @@ static int bmp_decode_frame(AVCodecContext *avctx, } switch (ihsize) { - case 40: // windib v3 + case 40: // windib + case 56: // windib v3 case 64: // OS/2 v2 case 108: // windib v4 case 124: // windib v5 @@ -107,7 +109,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, depth = bytestream_get_le16(&buf); - if (ihsize == 40) + if (ihsize >= 40) comp = bytestream_get_le32(&buf); else comp = BMP_RGB; @@ -123,6 +125,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, rgb[0] = bytestream_get_le32(&buf); rgb[1] = bytestream_get_le32(&buf); rgb[2] = bytestream_get_le32(&buf); + alpha = bytestream_get_le32(&buf); } avctx->width = width; @@ -133,21 +136,21 @@ static int bmp_decode_frame(AVCodecContext *avctx, switch (depth) { case 32: if (comp == BMP_BITFIELDS) { - rgb[0] = (rgb[0] >> 15) & 3; - rgb[1] = (rgb[1] >> 15) & 3; - rgb[2] = (rgb[2] >> 15) & 3; - - if (rgb[0] + rgb[1] + rgb[2] != 3 || - rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]) { - break; + if (rgb[0] == 0xFF000000 && rgb[1] == 0x00FF0000 && rgb[2] == 0x0000FF00) + avctx->pix_fmt = alpha ? AV_PIX_FMT_ABGR : AV_PIX_FMT_0BGR; + else if (rgb[0] == 0x00FF0000 && rgb[1] == 0x0000FF00 && rgb[2] == 0x000000FF) + avctx->pix_fmt = alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR0; + else if (rgb[0] == 0x0000FF00 && rgb[1] == 0x00FF0000 && rgb[2] == 0xFF000000) + avctx->pix_fmt = alpha ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB; + else if (rgb[0] == 0x000000FF && rgb[1] == 0x0000FF00 && rgb[2] == 0x00FF0000) + avctx->pix_fmt = alpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB0; + else { + av_log(avctx, AV_LOG_ERROR, "Unknown bitfields %0X %0X %0X\n", rgb[0], rgb[1], rgb[2]); + return AVERROR(EINVAL); } } else { - rgb[0] = 2; - rgb[1] = 1; - rgb[2] = 0; + avctx->pix_fmt = AV_PIX_FMT_BGRA; } - - avctx->pix_fmt = AV_PIX_FMT_BGR24; break; case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; @@ -193,10 +196,8 @@ static int bmp_decode_frame(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - 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; p->key_frame = 1; @@ -204,7 +205,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, dsize = buf_size - hsize; /* Line size in file multiple of 4 */ - n = ((avctx->width * depth) / 8 + 3) & ~3; + n = ((avctx->width * depth + 31) / 8) & ~3; if (n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8) { av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", @@ -242,11 +243,15 @@ static int bmp_decode_frame(AVCodecContext *avctx, buf = buf0 + 14 + ihsize; //palette location // OS/2 bitmap, 3 bytes per palette entry if ((hsize-ihsize-14) < (colors << 2)) { + if ((hsize-ihsize-14) < colors * 3) { + av_log(avctx, AV_LOG_ERROR, "palette doesnt fit in packet\n"); + return AVERROR_INVALIDDATA; + } for (i = 0; i < colors; i++) - ((uint32_t*)p->data[1])[i] = bytestream_get_le24(&buf); + ((uint32_t*)p->data[1])[i] = (0xFFU<<24) | bytestream_get_le24(&buf); } else { for (i = 0; i < colors; i++) - ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf); + ((uint32_t*)p->data[1])[i] = 0xFFU << 24 | bytestream_get_le32(&buf); } buf = buf0 + hsize; } @@ -282,6 +287,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, break; case 8: case 24: + case 32: for (i = 0; i < avctx->height; i++) { memcpy(ptr, buf, n); buf += n; @@ -311,23 +317,6 @@ static int bmp_decode_frame(AVCodecContext *avctx, ptr += linesize; } break; - case 32: - for (i = 0; i < avctx->height; i++) { - const uint8_t *src = buf; - uint8_t *dst = ptr; - - for (j = 0; j < avctx->width; j++) { - dst[0] = src[rgb[2]]; - dst[1] = src[rgb[1]]; - dst[2] = src[rgb[0]]; - dst += 3; - src += 4; - } - - buf += n; - ptr += linesize; - } - break; default: av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n"); return AVERROR_INVALIDDATA; |