• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/bmp.c

Go to the documentation of this file.
00001 /*
00002  * BMP image format decoder
00003  * Copyright (c) 2005 Mans Rullgard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "avcodec.h"
00023 #include "bytestream.h"
00024 #include "bmp.h"
00025 #include "msrledec.h"
00026 
00027 static av_cold int bmp_decode_init(AVCodecContext *avctx){
00028     BMPContext *s = avctx->priv_data;
00029 
00030     avcodec_get_frame_defaults((AVFrame*)&s->picture);
00031     avctx->coded_frame = (AVFrame*)&s->picture;
00032 
00033     return 0;
00034 }
00035 
00036 static int bmp_decode_frame(AVCodecContext *avctx,
00037                             void *data, int *data_size,
00038                             AVPacket *avpkt)
00039 {
00040     const uint8_t *buf = avpkt->data;
00041     int buf_size = avpkt->size;
00042     BMPContext *s = avctx->priv_data;
00043     AVFrame *picture = data;
00044     AVFrame *p = &s->picture;
00045     unsigned int fsize, hsize;
00046     int width, height;
00047     unsigned int depth;
00048     BiCompression comp;
00049     unsigned int ihsize;
00050     int i, j, n, linesize;
00051     uint32_t rgb[3];
00052     uint8_t *ptr;
00053     int dsize;
00054     const uint8_t *buf0 = buf;
00055 
00056     if(buf_size < 14){
00057         av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
00058         return -1;
00059     }
00060 
00061     if(bytestream_get_byte(&buf) != 'B' ||
00062        bytestream_get_byte(&buf) != 'M') {
00063         av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
00064         return -1;
00065     }
00066 
00067     fsize = bytestream_get_le32(&buf);
00068     if(buf_size < fsize){
00069         av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n",
00070                buf_size, fsize);
00071         fsize = buf_size;
00072     }
00073 
00074     buf += 2; /* reserved1 */
00075     buf += 2; /* reserved2 */
00076 
00077     hsize = bytestream_get_le32(&buf); /* header size */
00078     ihsize = bytestream_get_le32(&buf);       /* more header size */
00079     if(ihsize + 14 > hsize){
00080         av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
00081         return -1;
00082     }
00083 
00084     /* sometimes file size is set to some headers size, set a real size in that case */
00085     if(fsize == 14 || fsize == ihsize + 14)
00086         fsize = buf_size - 2;
00087 
00088     if(fsize <= hsize){
00089         av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n",
00090                fsize, hsize);
00091         return -1;
00092     }
00093 
00094     switch(ihsize){
00095     case  40: // windib v3
00096     case  64: // OS/2 v2
00097     case 108: // windib v4
00098     case 124: // windib v5
00099         width = bytestream_get_le32(&buf);
00100         height = bytestream_get_le32(&buf);
00101         break;
00102     case  12: // OS/2 v1
00103         width  = bytestream_get_le16(&buf);
00104         height = bytestream_get_le16(&buf);
00105         break;
00106     default:
00107         av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n");
00108         return -1;
00109     }
00110 
00111     if(bytestream_get_le16(&buf) != 1){ /* planes */
00112         av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
00113         return -1;
00114     }
00115 
00116     depth = bytestream_get_le16(&buf);
00117 
00118     if(ihsize == 40)
00119         comp = bytestream_get_le32(&buf);
00120     else
00121         comp = BMP_RGB;
00122 
00123     if(comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && comp != BMP_RLE8){
00124         av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
00125         return -1;
00126     }
00127 
00128     if(comp == BMP_BITFIELDS){
00129         buf += 20;
00130         rgb[0] = bytestream_get_le32(&buf);
00131         rgb[1] = bytestream_get_le32(&buf);
00132         rgb[2] = bytestream_get_le32(&buf);
00133     }
00134 
00135     avctx->width = width;
00136     avctx->height = height > 0? height: -height;
00137 
00138     avctx->pix_fmt = PIX_FMT_NONE;
00139 
00140     switch(depth){
00141     case 32:
00142         if(comp == BMP_BITFIELDS){
00143             rgb[0] = (rgb[0] >> 15) & 3;
00144             rgb[1] = (rgb[1] >> 15) & 3;
00145             rgb[2] = (rgb[2] >> 15) & 3;
00146 
00147             if(rgb[0] + rgb[1] + rgb[2] != 3 ||
00148                rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){
00149                 break;
00150             }
00151         } else {
00152             rgb[0] = 2;
00153             rgb[1] = 1;
00154             rgb[2] = 0;
00155         }
00156 
00157         avctx->pix_fmt = PIX_FMT_BGR24;
00158         break;
00159     case 24:
00160         avctx->pix_fmt = PIX_FMT_BGR24;
00161         break;
00162     case 16:
00163         if(comp == BMP_RGB)
00164             avctx->pix_fmt = PIX_FMT_RGB555;
00165         if(comp == BMP_BITFIELDS)
00166             avctx->pix_fmt = rgb[1] == 0x07E0 ? PIX_FMT_RGB565 : PIX_FMT_RGB555;
00167         break;
00168     case 8:
00169         if(hsize - ihsize - 14 > 0)
00170             avctx->pix_fmt = PIX_FMT_PAL8;
00171         else
00172             avctx->pix_fmt = PIX_FMT_GRAY8;
00173         break;
00174     case 4:
00175         if(hsize - ihsize - 14 > 0){
00176             avctx->pix_fmt = PIX_FMT_PAL8;
00177         }else{
00178             av_log(avctx, AV_LOG_ERROR, "Unknown palette for 16-colour BMP\n");
00179             return -1;
00180         }
00181         break;
00182     case 1:
00183         avctx->pix_fmt = PIX_FMT_MONOBLACK;
00184         break;
00185     default:
00186         av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
00187         return -1;
00188     }
00189 
00190     if(avctx->pix_fmt == PIX_FMT_NONE){
00191         av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
00192         return -1;
00193     }
00194 
00195     if(p->data[0])
00196         avctx->release_buffer(avctx, p);
00197 
00198     p->reference = 0;
00199     if(avctx->get_buffer(avctx, p) < 0){
00200         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00201         return -1;
00202     }
00203     p->pict_type = FF_I_TYPE;
00204     p->key_frame = 1;
00205 
00206     buf = buf0 + hsize;
00207     dsize = buf_size - hsize;
00208 
00209     /* Line size in file multiple of 4 */
00210     n = ((avctx->width * depth) / 8 + 3) & ~3;
00211 
00212     if(n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8){
00213         av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
00214                dsize, n * avctx->height);
00215         return -1;
00216     }
00217 
00218     // RLE may skip decoding some picture areas, so blank picture before decoding
00219     if(comp == BMP_RLE4 || comp == BMP_RLE8)
00220         memset(p->data[0], 0, avctx->height * p->linesize[0]);
00221 
00222     if(depth == 4 || depth == 8)
00223         memset(p->data[1], 0, 1024);
00224 
00225     if(height > 0){
00226         ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
00227         linesize = -p->linesize[0];
00228     } else {
00229         ptr = p->data[0];
00230         linesize = p->linesize[0];
00231     }
00232 
00233     if(avctx->pix_fmt == PIX_FMT_PAL8){
00234         int colors = 1 << depth;
00235         if(ihsize >= 36){
00236             int t;
00237             buf = buf0 + 46;
00238             t = bytestream_get_le32(&buf);
00239             if(t < 0 || t > (1 << depth)){
00240                 av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth);
00241             }else if(t){
00242                 colors = t;
00243             }
00244         }
00245         buf = buf0 + 14 + ihsize; //palette location
00246         if((hsize-ihsize-14) < (colors << 2)){ // OS/2 bitmap, 3 bytes per palette entry
00247             for(i = 0; i < colors; i++)
00248                 ((uint32_t*)p->data[1])[i] = bytestream_get_le24(&buf);
00249         }else{
00250             for(i = 0; i < colors; i++)
00251                 ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf);
00252         }
00253         buf = buf0 + hsize;
00254     }
00255     if(comp == BMP_RLE4 || comp == BMP_RLE8){
00256         if(height < 0){
00257             p->data[0] += p->linesize[0] * (avctx->height - 1);
00258             p->linesize[0] = -p->linesize[0];
00259         }
00260         ff_msrle_decode(avctx, (AVPicture*)p, depth, buf, dsize);
00261         if(height < 0){
00262             p->data[0] += p->linesize[0] * (avctx->height - 1);
00263             p->linesize[0] = -p->linesize[0];
00264         }
00265     }else{
00266         switch(depth){
00267         case 1:
00268         case 8:
00269         case 24:
00270             for(i = 0; i < avctx->height; i++){
00271                 memcpy(ptr, buf, n);
00272                 buf += n;
00273                 ptr += linesize;
00274             }
00275             break;
00276         case 4:
00277             for(i = 0; i < avctx->height; i++){
00278                 int j;
00279                 for(j = 0; j < n; j++){
00280                     ptr[j*2+0] = (buf[j] >> 4) & 0xF;
00281                     ptr[j*2+1] = buf[j] & 0xF;
00282                 }
00283                 buf += n;
00284                 ptr += linesize;
00285             }
00286             break;
00287         case 16:
00288             for(i = 0; i < avctx->height; i++){
00289                 const uint16_t *src = (const uint16_t *) buf;
00290                 uint16_t *dst = (uint16_t *) ptr;
00291 
00292                 for(j = 0; j < avctx->width; j++)
00293                     *dst++ = le2me_16(*src++);
00294 
00295                 buf += n;
00296                 ptr += linesize;
00297             }
00298             break;
00299         case 32:
00300             for(i = 0; i < avctx->height; i++){
00301                 const uint8_t *src = buf;
00302                 uint8_t *dst = ptr;
00303 
00304                 for(j = 0; j < avctx->width; j++){
00305                     dst[0] = src[rgb[2]];
00306                     dst[1] = src[rgb[1]];
00307                     dst[2] = src[rgb[0]];
00308                     dst += 3;
00309                     src += 4;
00310                 }
00311 
00312                 buf += n;
00313                 ptr += linesize;
00314             }
00315             break;
00316         default:
00317             av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");
00318             return -1;
00319         }
00320     }
00321 
00322     *picture = s->picture;
00323     *data_size = sizeof(AVPicture);
00324 
00325     return buf_size;
00326 }
00327 
00328 static av_cold int bmp_decode_end(AVCodecContext *avctx)
00329 {
00330     BMPContext* c = avctx->priv_data;
00331 
00332     if (c->picture.data[0])
00333         avctx->release_buffer(avctx, &c->picture);
00334 
00335     return 0;
00336 }
00337 
00338 AVCodec bmp_decoder = {
00339     "bmp",
00340     AVMEDIA_TYPE_VIDEO,
00341     CODEC_ID_BMP,
00342     sizeof(BMPContext),
00343     bmp_decode_init,
00344     NULL,
00345     bmp_decode_end,
00346     bmp_decode_frame,
00347     CODEC_CAP_DR1,
00348     .long_name = NULL_IF_CONFIG_SMALL("BMP image"),
00349 };

Generated on Fri Sep 16 2011 17:17:34 for FFmpeg by  doxygen 1.7.1