00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 const uint8_t *buf, int buf_size)
00039 {
00040 BMPContext *s = avctx->priv_data;
00041 AVFrame *picture = data;
00042 AVFrame *p = &s->picture;
00043 unsigned int fsize, hsize;
00044 int width, height;
00045 unsigned int depth;
00046 BiCompression comp;
00047 unsigned int ihsize;
00048 int i, j, n, linesize;
00049 uint32_t rgb[3];
00050 uint8_t *ptr;
00051 int dsize;
00052 const uint8_t *buf0 = buf;
00053
00054 if(buf_size < 14){
00055 av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
00056 return -1;
00057 }
00058
00059 if(bytestream_get_byte(&buf) != 'B' ||
00060 bytestream_get_byte(&buf) != 'M') {
00061 av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
00062 return -1;
00063 }
00064
00065 fsize = bytestream_get_le32(&buf);
00066 if(buf_size < fsize){
00067 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n",
00068 buf_size, fsize);
00069 fsize = buf_size;
00070 }
00071
00072 buf += 2;
00073 buf += 2;
00074
00075 hsize = bytestream_get_le32(&buf);
00076 ihsize = bytestream_get_le32(&buf);
00077 if(ihsize + 14 > hsize){
00078 av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
00079 return -1;
00080 }
00081
00082
00083 if(fsize == 14 || fsize == ihsize + 14)
00084 fsize = buf_size - 2;
00085
00086 if(fsize <= hsize){
00087 av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n",
00088 fsize, hsize);
00089 return -1;
00090 }
00091
00092 switch(ihsize){
00093 case 40:
00094 case 64:
00095 case 108:
00096 case 124:
00097 width = bytestream_get_le32(&buf);
00098 height = bytestream_get_le32(&buf);
00099 break;
00100 case 12:
00101 width = bytestream_get_le16(&buf);
00102 height = bytestream_get_le16(&buf);
00103 break;
00104 default:
00105 av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n");
00106 return -1;
00107 }
00108
00109 if(bytestream_get_le16(&buf) != 1){
00110 av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
00111 return -1;
00112 }
00113
00114 depth = bytestream_get_le16(&buf);
00115
00116 if(ihsize == 40)
00117 comp = bytestream_get_le32(&buf);
00118 else
00119 comp = BMP_RGB;
00120
00121 if(comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && comp != BMP_RLE8){
00122 av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
00123 return -1;
00124 }
00125
00126 if(comp == BMP_BITFIELDS){
00127 buf += 20;
00128 rgb[0] = bytestream_get_le32(&buf);
00129 rgb[1] = bytestream_get_le32(&buf);
00130 rgb[2] = bytestream_get_le32(&buf);
00131 }
00132
00133 avctx->width = width;
00134 avctx->height = height > 0? height: -height;
00135
00136 avctx->pix_fmt = PIX_FMT_NONE;
00137
00138 switch(depth){
00139 case 32:
00140 if(comp == BMP_BITFIELDS){
00141 rgb[0] = (rgb[0] >> 15) & 3;
00142 rgb[1] = (rgb[1] >> 15) & 3;
00143 rgb[2] = (rgb[2] >> 15) & 3;
00144
00145 if(rgb[0] + rgb[1] + rgb[2] != 3 ||
00146 rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){
00147 break;
00148 }
00149 } else {
00150 rgb[0] = 2;
00151 rgb[1] = 1;
00152 rgb[2] = 0;
00153 }
00154
00155 avctx->pix_fmt = PIX_FMT_BGR24;
00156 break;
00157 case 24:
00158 avctx->pix_fmt = PIX_FMT_BGR24;
00159 break;
00160 case 16:
00161 if(comp == BMP_RGB)
00162 avctx->pix_fmt = PIX_FMT_RGB555;
00163 if(comp == BMP_BITFIELDS)
00164 avctx->pix_fmt = rgb[1] == 0x07E0 ? PIX_FMT_RGB565 : PIX_FMT_RGB555;
00165 break;
00166 case 8:
00167 if(hsize - ihsize - 14 > 0)
00168 avctx->pix_fmt = PIX_FMT_PAL8;
00169 else
00170 avctx->pix_fmt = PIX_FMT_GRAY8;
00171 break;
00172 case 4:
00173 if(hsize - ihsize - 14 > 0){
00174 avctx->pix_fmt = PIX_FMT_PAL8;
00175 }else{
00176 av_log(avctx, AV_LOG_ERROR, "Unknown palette for 16-colour BMP\n");
00177 return -1;
00178 }
00179 break;
00180 case 1:
00181 avctx->pix_fmt = PIX_FMT_MONOBLACK;
00182 break;
00183 default:
00184 av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
00185 return -1;
00186 }
00187
00188 if(avctx->pix_fmt == PIX_FMT_NONE){
00189 av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
00190 return -1;
00191 }
00192
00193 if(p->data[0])
00194 avctx->release_buffer(avctx, p);
00195
00196 p->reference = 0;
00197 if(avctx->get_buffer(avctx, p) < 0){
00198 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00199 return -1;
00200 }
00201 p->pict_type = FF_I_TYPE;
00202 p->key_frame = 1;
00203
00204 buf = buf0 + hsize;
00205 dsize = buf_size - hsize;
00206
00207
00208 n = ((avctx->width * depth) / 8 + 3) & ~3;
00209
00210 if(n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8){
00211 av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
00212 dsize, n * avctx->height);
00213 return -1;
00214 }
00215
00216
00217 if(comp == BMP_RLE4 || comp == BMP_RLE8)
00218 memset(p->data[0], 0, avctx->height * p->linesize[0]);
00219
00220 if(depth == 4 || depth == 8)
00221 memset(p->data[1], 0, 1024);
00222
00223 if(height > 0){
00224 ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
00225 linesize = -p->linesize[0];
00226 } else {
00227 ptr = p->data[0];
00228 linesize = p->linesize[0];
00229 }
00230
00231 if(avctx->pix_fmt == PIX_FMT_PAL8){
00232 buf = buf0 + 14 + ihsize;
00233 if((hsize-ihsize-14)>>depth < 4){
00234 for(i = 0; i < (1 << depth); i++)
00235 ((uint32_t*)p->data[1])[i] = bytestream_get_le24(&buf);
00236 }else{
00237 for(i = 0; i < (1 << depth); i++)
00238 ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf);
00239 }
00240 buf = buf0 + hsize;
00241 }
00242 if(comp == BMP_RLE4 || comp == BMP_RLE8){
00243 ff_msrle_decode(avctx, (AVPicture*)p, depth, buf, dsize);
00244 }else{
00245 switch(depth){
00246 case 1:
00247 for(i = 0; i < avctx->height; i++){
00248 memcpy(ptr, buf, n);
00249 buf += n;
00250 ptr += linesize;
00251 }
00252 break;
00253 case 4:
00254 for(i = 0; i < avctx->height; i++){
00255 int j;
00256 for(j = 0; j < n; j++){
00257 ptr[j*2+0] = (buf[j] >> 4) & 0xF;
00258 ptr[j*2+1] = buf[j] & 0xF;
00259 }
00260 buf += n;
00261 ptr += linesize;
00262 }
00263 break;
00264 case 8:
00265 for(i = 0; i < avctx->height; i++){
00266 memcpy(ptr, buf, avctx->width);
00267 buf += n;
00268 ptr += linesize;
00269 }
00270 break;
00271 case 24:
00272 for(i = 0; i < avctx->height; i++){
00273 memcpy(ptr, buf, avctx->width*(depth>>3));
00274 buf += n;
00275 ptr += linesize;
00276 }
00277 break;
00278 case 16:
00279 for(i = 0; i < avctx->height; i++){
00280 const uint16_t *src = (const uint16_t *) buf;
00281 uint16_t *dst = (uint16_t *) ptr;
00282
00283 for(j = 0; j < avctx->width; j++)
00284 *dst++ = le2me_16(*src++);
00285
00286 buf += n;
00287 ptr += linesize;
00288 }
00289 break;
00290 case 32:
00291 for(i = 0; i < avctx->height; i++){
00292 const uint8_t *src = buf;
00293 uint8_t *dst = ptr;
00294
00295 for(j = 0; j < avctx->width; j++){
00296 dst[0] = src[rgb[2]];
00297 dst[1] = src[rgb[1]];
00298 dst[2] = src[rgb[0]];
00299 dst += 3;
00300 src += 4;
00301 }
00302
00303 buf += n;
00304 ptr += linesize;
00305 }
00306 break;
00307 default:
00308 av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");
00309 return -1;
00310 }
00311 }
00312
00313 *picture = s->picture;
00314 *data_size = sizeof(AVPicture);
00315
00316 return buf_size;
00317 }
00318
00319 static av_cold int bmp_decode_end(AVCodecContext *avctx)
00320 {
00321 BMPContext* c = avctx->priv_data;
00322
00323 if (c->picture.data[0])
00324 avctx->release_buffer(avctx, &c->picture);
00325
00326 return 0;
00327 }
00328
00329 AVCodec bmp_decoder = {
00330 "bmp",
00331 CODEC_TYPE_VIDEO,
00332 CODEC_ID_BMP,
00333 sizeof(BMPContext),
00334 bmp_decode_init,
00335 NULL,
00336 bmp_decode_end,
00337 bmp_decode_frame,
00338 .long_name = NULL_IF_CONFIG_SMALL("BMP image"),
00339 };