bmp.c 9.81 KB
Newer Older
Måns Rullgård's avatar
Måns Rullgård committed
1
/*
2
 * BMP image format decoder
Måns Rullgård's avatar
Måns Rullgård committed
3 4
 * Copyright (c) 2005 Mans Rullgard
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
Måns Rullgård's avatar
Måns Rullgård committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Måns Rullgård's avatar
Måns Rullgård committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Måns Rullgård's avatar
Måns Rullgård committed
13 14 15 16 17
 * 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
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Måns Rullgård's avatar
Måns Rullgård committed
20 21 22
 */

#include "avcodec.h"
23
#include "bytestream.h"
24
#include "bmp.h"
25
#include "msrledec.h"
Måns Rullgård's avatar
Måns Rullgård committed
26

27
static av_cold int bmp_decode_init(AVCodecContext *avctx){
Måns Rullgård's avatar
Måns Rullgård committed
28 29 30 31 32 33 34 35
    BMPContext *s = avctx->priv_data;

    avcodec_get_frame_defaults((AVFrame*)&s->picture);
    avctx->coded_frame = (AVFrame*)&s->picture;

    return 0;
}

36
static int bmp_decode_frame(AVCodecContext *avctx,
Måns Rullgård's avatar
Måns Rullgård committed
37
                            void *data, int *data_size,
38
                            AVPacket *avpkt)
Måns Rullgård's avatar
Måns Rullgård committed
39
{
40 41
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
Måns Rullgård's avatar
Måns Rullgård committed
42 43 44 45 46 47
    BMPContext *s = avctx->priv_data;
    AVFrame *picture = data;
    AVFrame *p = &s->picture;
    unsigned int fsize, hsize;
    int width, height;
    unsigned int depth;
Michael Niedermayer's avatar
Michael Niedermayer committed
48
    BiCompression comp;
Måns Rullgård's avatar
Måns Rullgård committed
49 50 51 52 53
    unsigned int ihsize;
    int i, j, n, linesize;
    uint32_t rgb[3];
    uint8_t *ptr;
    int dsize;
Michael Niedermayer's avatar
Michael Niedermayer committed
54
    const uint8_t *buf0 = buf;
Måns Rullgård's avatar
Måns Rullgård committed
55 56 57 58 59 60

    if(buf_size < 14){
        av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
        return -1;
    }

61 62
    if(bytestream_get_byte(&buf) != 'B' ||
       bytestream_get_byte(&buf) != 'M') {
Måns Rullgård's avatar
Måns Rullgård committed
63 64 65 66
        av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
        return -1;
    }

67
    fsize = bytestream_get_le32(&buf);
Måns Rullgård's avatar
Måns Rullgård committed
68
    if(buf_size < fsize){
69
        av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n",
Måns Rullgård's avatar
Måns Rullgård committed
70
               buf_size, fsize);
71
        fsize = buf_size;
Måns Rullgård's avatar
Måns Rullgård committed
72 73
    }

74 75
    buf += 2; /* reserved1 */
    buf += 2; /* reserved2 */
Måns Rullgård's avatar
Måns Rullgård committed
76

77 78
    hsize = bytestream_get_le32(&buf); /* header size */
    ihsize = bytestream_get_le32(&buf);       /* more header size */
Måns Rullgård's avatar
Måns Rullgård committed
79 80 81 82 83
    if(ihsize + 14 > hsize){
        av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
        return -1;
    }

84 85 86 87 88 89 90 91 92 93
    /* sometimes file size is set to some headers size, set a real size in that case */
    if(fsize == 14 || fsize == ihsize + 14)
        fsize = buf_size - 2;

    if(fsize <= hsize){
        av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n",
               fsize, hsize);
        return -1;
    }

94 95 96 97 98
    switch(ihsize){
    case  40: // windib v3
    case  64: // OS/2 v2
    case 108: // windib v4
    case 124: // windib v5
Benoit Fouet's avatar
Benoit Fouet committed
99 100
        width = bytestream_get_le32(&buf);
        height = bytestream_get_le32(&buf);
101 102
        break;
    case  12: // OS/2 v1
Benoit Fouet's avatar
Benoit Fouet committed
103 104
        width  = bytestream_get_le16(&buf);
        height = bytestream_get_le16(&buf);
105 106
        break;
    default:
107
        av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n");
Benoit Fouet's avatar
Benoit Fouet committed
108 109
        return -1;
    }
Måns Rullgård's avatar
Måns Rullgård committed
110

111
    if(bytestream_get_le16(&buf) != 1){ /* planes */
Måns Rullgård's avatar
Måns Rullgård committed
112 113 114 115
        av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
        return -1;
    }

116
    depth = bytestream_get_le16(&buf);
Måns Rullgård's avatar
Måns Rullgård committed
117

Benoit Fouet's avatar
Benoit Fouet committed
118
    if(ihsize == 40)
119
        comp = bytestream_get_le32(&buf);
Måns Rullgård's avatar
Måns Rullgård committed
120 121 122
    else
        comp = BMP_RGB;

123
    if(comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && comp != BMP_RLE8){
Måns Rullgård's avatar
Måns Rullgård committed
124 125 126 127 128
        av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
        return -1;
    }

    if(comp == BMP_BITFIELDS){
129 130 131 132
        buf += 20;
        rgb[0] = bytestream_get_le32(&buf);
        rgb[1] = bytestream_get_le32(&buf);
        rgb[2] = bytestream_get_le32(&buf);
Måns Rullgård's avatar
Måns Rullgård committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    }

    avctx->width = width;
    avctx->height = height > 0? height: -height;

    avctx->pix_fmt = PIX_FMT_NONE;

    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;
            }
        } else {
            rgb[0] = 2;
            rgb[1] = 1;
            rgb[2] = 0;
        }

        avctx->pix_fmt = PIX_FMT_BGR24;
        break;
    case 24:
        avctx->pix_fmt = PIX_FMT_BGR24;
        break;
    case 16:
        if(comp == BMP_RGB)
            avctx->pix_fmt = PIX_FMT_RGB555;
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
        if(comp == BMP_BITFIELDS)
            avctx->pix_fmt = rgb[1] == 0x07E0 ? PIX_FMT_RGB565 : PIX_FMT_RGB555;
        break;
    case 8:
        if(hsize - ihsize - 14 > 0)
            avctx->pix_fmt = PIX_FMT_PAL8;
        else
            avctx->pix_fmt = PIX_FMT_GRAY8;
        break;
    case 4:
        if(hsize - ihsize - 14 > 0){
            avctx->pix_fmt = PIX_FMT_PAL8;
        }else{
            av_log(avctx, AV_LOG_ERROR, "Unknown palette for 16-colour BMP\n");
            return -1;
        }
        break;
    case 1:
        avctx->pix_fmt = PIX_FMT_MONOBLACK;
Måns Rullgård's avatar
Måns Rullgård committed
184 185 186 187 188 189 190 191 192 193 194
        break;
    default:
        av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
        return -1;
    }

    if(avctx->pix_fmt == PIX_FMT_NONE){
        av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
        return -1;
    }

195 196 197
    if(p->data[0])
        avctx->release_buffer(avctx, p);

Måns Rullgård's avatar
Måns Rullgård committed
198 199 200 201 202 203 204 205
    p->reference = 0;
    if(avctx->get_buffer(avctx, p) < 0){
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
        return -1;
    }
    p->pict_type = FF_I_TYPE;
    p->key_frame = 1;

206
    buf = buf0 + hsize;
Måns Rullgård's avatar
Måns Rullgård committed
207 208
    dsize = buf_size - hsize;

209
    /* Line size in file multiple of 4 */
210
    n = ((avctx->width * depth) / 8 + 3) & ~3;
Måns Rullgård's avatar
Måns Rullgård committed
211

212
    if(n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8){
Måns Rullgård's avatar
Måns Rullgård committed
213 214 215 216 217
        av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
               dsize, n * avctx->height);
        return -1;
    }

218 219 220 221
    // RLE may skip decoding some picture areas, so blank picture before decoding
    if(comp == BMP_RLE4 || comp == BMP_RLE8)
        memset(p->data[0], 0, avctx->height * p->linesize[0]);

222 223 224
    if(depth == 4 || depth == 8)
        memset(p->data[1], 0, 1024);

Måns Rullgård's avatar
Måns Rullgård committed
225 226 227 228 229 230 231 232
    if(height > 0){
        ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
        linesize = -p->linesize[0];
    } else {
        ptr = p->data[0];
        linesize = p->linesize[0];
    }

233
    if(avctx->pix_fmt == PIX_FMT_PAL8){
234 235 236 237 238 239 240 241 242 243 244
        int colors = 1 << depth;
        if(ihsize >= 36){
            int t;
            buf = buf0 + 46;
            t = bytestream_get_le32(&buf);
            if(t < 0 || t > (1 << depth)){
                av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth);
            }else if(t){
                colors = t;
            }
        }
245
        buf = buf0 + 14 + ihsize; //palette location
246 247
        if((hsize-ihsize-14) < (colors << 2)){ // OS/2 bitmap, 3 bytes per palette entry
            for(i = 0; i < colors; i++)
248 249
                ((uint32_t*)p->data[1])[i] = bytestream_get_le24(&buf);
        }else{
250
            for(i = 0; i < colors; i++)
251 252 253 254
                ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf);
        }
        buf = buf0 + hsize;
    }
255
    if(comp == BMP_RLE4 || comp == BMP_RLE8){
256 257 258 259
        if(height < 0){
            p->data[0] += p->linesize[0] * (avctx->height - 1);
            p->linesize[0] = -p->linesize[0];
        }
260
        ff_msrle_decode(avctx, (AVPicture*)p, depth, buf, dsize);
261 262 263 264
        if(height < 0){
            p->data[0] += p->linesize[0] * (avctx->height - 1);
            p->linesize[0] = -p->linesize[0];
        }
265
    }else{
266 267
        switch(depth){
        case 1:
268 269
        case 8:
        case 24:
270 271 272 273
            for(i = 0; i < avctx->height; i++){
                memcpy(ptr, buf, n);
                buf += n;
                ptr += linesize;
274
            }
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
            break;
        case 4:
            for(i = 0; i < avctx->height; i++){
                int j;
                for(j = 0; j < n; j++){
                    ptr[j*2+0] = (buf[j] >> 4) & 0xF;
                    ptr[j*2+1] = buf[j] & 0xF;
                }
                buf += n;
                ptr += linesize;
            }
            break;
        case 16:
            for(i = 0; i < avctx->height; i++){
                const uint16_t *src = (const uint16_t *) buf;
                uint16_t *dst = (uint16_t *) ptr;
Måns Rullgård's avatar
Måns Rullgård committed
291

292 293
                for(j = 0; j < avctx->width; j++)
                    *dst++ = le2me_16(*src++);
Måns Rullgård's avatar
Måns Rullgård committed
294

295 296
                buf += n;
                ptr += linesize;
Måns Rullgård's avatar
Måns Rullgård committed
297
            }
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
            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 -1;
Måns Rullgård's avatar
Måns Rullgård committed
319
        }
320
    }
Måns Rullgård's avatar
Måns Rullgård committed
321 322 323 324 325 326 327

    *picture = s->picture;
    *data_size = sizeof(AVPicture);

    return buf_size;
}

328
static av_cold int bmp_decode_end(AVCodecContext *avctx)
329 330 331 332 333 334 335 336 337
{
    BMPContext* c = avctx->priv_data;

    if (c->picture.data[0])
        avctx->release_buffer(avctx, &c->picture);

    return 0;
}

Måns Rullgård's avatar
Måns Rullgård committed
338 339 340 341 342 343 344
AVCodec bmp_decoder = {
    "bmp",
    CODEC_TYPE_VIDEO,
    CODEC_ID_BMP,
    sizeof(BMPContext),
    bmp_decode_init,
    NULL,
345
    bmp_decode_end,
346
    bmp_decode_frame,
347
    CODEC_CAP_DR1,
348
    .long_name = NULL_IF_CONFIG_SMALL("BMP image"),
Måns Rullgård's avatar
Måns Rullgård committed
349
};