bmp.c 9.44 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,
Michael Niedermayer's avatar
Michael Niedermayer committed
38
                            const uint8_t *buf, int buf_size)
Måns Rullgård's avatar
Måns Rullgård committed
39 40 41 42 43 44 45
{
    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
46
    BiCompression comp;
Måns Rullgård's avatar
Måns Rullgård committed
47 48 49 50 51
    unsigned int ihsize;
    int i, j, n, linesize;
    uint32_t rgb[3];
    uint8_t *ptr;
    int dsize;
Michael Niedermayer's avatar
Michael Niedermayer committed
52
    const uint8_t *buf0 = buf;
Måns Rullgård's avatar
Måns Rullgård committed
53 54 55 56 57 58

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

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

65
    fsize = bytestream_get_le32(&buf);
Måns Rullgård's avatar
Måns Rullgård committed
66 67 68 69 70 71
    if(buf_size < fsize){
        av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
               buf_size, fsize);
        return -1;
    }

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

75 76
    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
77 78 79 80 81
    if(ihsize + 14 > hsize){
        av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
        return -1;
    }

82 83 84 85 86 87 88 89 90 91
    /* 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;
    }

92 93 94 95 96
    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
97 98
        width = bytestream_get_le32(&buf);
        height = bytestream_get_le32(&buf);
99 100
        break;
    case  12: // OS/2 v1
Benoit Fouet's avatar
Benoit Fouet committed
101 102
        width  = bytestream_get_le16(&buf);
        height = bytestream_get_le16(&buf);
103 104
        break;
    default:
105
        av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n");
Benoit Fouet's avatar
Benoit Fouet committed
106 107
        return -1;
    }
Måns Rullgård's avatar
Måns Rullgård committed
108

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

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

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

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

    if(comp == BMP_BITFIELDS){
127 128 129 130
        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
131 132 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
    }

    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;
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        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
182 183 184 185 186 187 188 189 190 191 192
        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;
    }

193 194 195
    if(p->data[0])
        avctx->release_buffer(avctx, p);

Måns Rullgård's avatar
Måns Rullgård committed
196 197 198 199 200 201 202 203
    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;

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

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

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

216 217 218 219
    // 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]);

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

Måns Rullgård's avatar
Måns Rullgård committed
223 224 225 226 227 228 229 230
    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];
    }

231 232 233 234 235 236 237 238 239 240 241
    if(avctx->pix_fmt == PIX_FMT_PAL8){
        buf = buf0 + 14 + ihsize; //palette location
        if((hsize-ihsize-14)>>depth < 4){ // OS/2 bitmap, 3 bytes per palette entry
            for(i = 0; i < (1 << depth); i++)
                ((uint32_t*)p->data[1])[i] = bytestream_get_le24(&buf);
        }else{
            for(i = 0; i < (1 << depth); i++)
                ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf);
        }
        buf = buf0 + hsize;
    }
242 243 244
    if(comp == BMP_RLE4 || comp == BMP_RLE8){
        ff_msrle_decode(avctx, p, depth, buf, dsize);
    }else{
245 246 247 248 249 250
        switch(depth){
        case 1:
            for(i = 0; i < avctx->height; i++){
                memcpy(ptr, buf, n);
                buf += n;
                ptr += linesize;
251
            }
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
            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 8:
            for(i = 0; i < avctx->height; i++){
                memcpy(ptr, buf, avctx->width);
                buf += n;
                ptr += linesize;
            }
            break;
        case 24:
            for(i = 0; i < avctx->height; i++){
                memcpy(ptr, buf, avctx->width*(depth>>3));
                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
282

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

286 287
                buf += n;
                ptr += linesize;
Måns Rullgård's avatar
Måns Rullgård committed
288
            }
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
            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
310
        }
311
    }
Måns Rullgård's avatar
Måns Rullgård committed
312 313 314 315 316 317 318

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

    return buf_size;
}

319
static av_cold int bmp_decode_end(AVCodecContext *avctx)
320 321 322 323 324 325 326 327 328
{
    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
329 330 331 332 333 334 335
AVCodec bmp_decoder = {
    "bmp",
    CODEC_TYPE_VIDEO,
    CODEC_ID_BMP,
    sizeof(BMPContext),
    bmp_decode_init,
    NULL,
336
    bmp_decode_end,
337
    bmp_decode_frame,
338
    .long_name = NULL_IF_CONFIG_SMALL("BMP image"),
Måns Rullgård's avatar
Måns Rullgård committed
339
};