| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-01-27 07:39:16 +00:00
										 |  |  |  * BMP image format decoder | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |  * Copyright (c) 2005 Mans Rullgard | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-01-12 22:43:26 +00:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "avcodec.h"
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  | #include "bytestream.h"
 | 
					
						
							| 
									
										
										
										
											2007-01-27 07:39:16 +00:00
										 |  |  | #include "bmp.h"
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  | #include "msrledec.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-21 03:11:20 +00:00
										 |  |  | static av_cold int bmp_decode_init(AVCodecContext *avctx){ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     BMPContext *s = avctx->priv_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     avcodec_get_frame_defaults((AVFrame*)&s->picture); | 
					
						
							|  |  |  |     avctx->coded_frame = (AVFrame*)&s->picture; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | static int bmp_decode_frame(AVCodecContext *avctx, | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |                             void *data, int *data_size, | 
					
						
							| 
									
										
										
										
											2009-04-07 15:59:50 +00:00
										 |  |  |                             AVPacket *avpkt) | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-07 15:59:50 +00:00
										 |  |  |     const uint8_t *buf = avpkt->data; | 
					
						
							|  |  |  |     int buf_size = avpkt->size; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     BMPContext *s = avctx->priv_data; | 
					
						
							|  |  |  |     AVFrame *picture = data; | 
					
						
							|  |  |  |     AVFrame *p = &s->picture; | 
					
						
							|  |  |  |     unsigned int fsize, hsize; | 
					
						
							|  |  |  |     int width, height; | 
					
						
							|  |  |  |     unsigned int depth; | 
					
						
							| 
									
										
										
										
											2007-01-24 10:41:03 +00:00
										 |  |  |     BiCompression comp; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     unsigned int ihsize; | 
					
						
							|  |  |  |     int i, j, n, linesize; | 
					
						
							|  |  |  |     uint32_t rgb[3]; | 
					
						
							|  |  |  |     uint8_t *ptr; | 
					
						
							|  |  |  |     int dsize; | 
					
						
							| 
									
										
										
										
											2008-02-01 15:01:05 +00:00
										 |  |  |     const uint8_t *buf0 = buf; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if(buf_size < 14){ | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     if(bytestream_get_byte(&buf) != 'B' || | 
					
						
							|  |  |  |        bytestream_get_byte(&buf) != 'M') { | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     fsize = bytestream_get_le32(&buf); | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     if(buf_size < fsize){ | 
					
						
							| 
									
										
										
										
											2009-02-16 06:57:11 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n", | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |                buf_size, fsize); | 
					
						
							| 
									
										
										
										
											2009-02-16 06:57:11 +00:00
										 |  |  |         fsize = buf_size; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     buf += 2; /* reserved1 */ | 
					
						
							|  |  |  |     buf += 2; /* reserved2 */ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     hsize = bytestream_get_le32(&buf); /* header size */ | 
					
						
							|  |  |  |     ihsize = bytestream_get_le32(&buf);       /* more header size */ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     if(ihsize + 14 > hsize){ | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-24 11:24:02 +00:00
										 |  |  |     /* 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-24 10:53:13 +00:00
										 |  |  |     switch(ihsize){ | 
					
						
							| 
									
										
										
										
											2011-12-08 02:14:36 +01:00
										 |  |  |     case  40: // windib
 | 
					
						
							|  |  |  |     case  56: // windib v3
 | 
					
						
							| 
									
										
										
										
											2008-11-24 10:53:13 +00:00
										 |  |  |     case  64: // OS/2 v2
 | 
					
						
							|  |  |  |     case 108: // windib v4
 | 
					
						
							|  |  |  |     case 124: // windib v5
 | 
					
						
							| 
									
										
										
										
											2008-04-14 13:15:16 +00:00
										 |  |  |         width = bytestream_get_le32(&buf); | 
					
						
							|  |  |  |         height = bytestream_get_le32(&buf); | 
					
						
							| 
									
										
										
										
											2008-11-24 10:53:13 +00:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case  12: // OS/2 v1
 | 
					
						
							| 
									
										
										
										
											2008-04-14 13:13:08 +00:00
										 |  |  |         width  = bytestream_get_le16(&buf); | 
					
						
							|  |  |  |         height = bytestream_get_le16(&buf); | 
					
						
							| 
									
										
										
										
											2008-11-24 10:53:13 +00:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2008-09-18 14:08:44 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n"); | 
					
						
							| 
									
										
										
										
											2008-04-14 13:13:08 +00:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     if(bytestream_get_le16(&buf) != 1){ /* planes */ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     depth = bytestream_get_le16(&buf); | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-08 02:14:36 +01:00
										 |  |  |     if(ihsize == 40 || ihsize == 64 || ihsize == 56) | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |         comp = bytestream_get_le32(&buf); | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     else | 
					
						
							|  |  |  |         comp = BMP_RGB; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     if(comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && comp != BMP_RLE8){ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(comp == BMP_BITFIELDS){ | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |         buf += 20; | 
					
						
							|  |  |  |         rgb[0] = bytestream_get_le32(&buf); | 
					
						
							|  |  |  |         rgb[1] = bytestream_get_le32(&buf); | 
					
						
							|  |  |  |         rgb[2] = bytestream_get_le32(&buf); | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-02 00:21:24 +01:00
										 |  |  |         avctx->pix_fmt = PIX_FMT_BGRA; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case 24: | 
					
						
							|  |  |  |         avctx->pix_fmt = PIX_FMT_BGR24; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case 16: | 
					
						
							|  |  |  |         if(comp == BMP_RGB) | 
					
						
							|  |  |  |             avctx->pix_fmt = PIX_FMT_RGB555; | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |     case 1: | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |     case 4: | 
					
						
							|  |  |  |         if(hsize - ihsize - 14 > 0){ | 
					
						
							|  |  |  |             avctx->pix_fmt = PIX_FMT_PAL8; | 
					
						
							|  |  |  |         }else{ | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |             av_log(avctx, AV_LOG_ERROR, "Unknown palette for %d-colour BMP\n", 1<<depth); | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-29 14:07:12 +00:00
										 |  |  |     if(p->data[0]) | 
					
						
							|  |  |  |         avctx->release_buffer(avctx, p); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     p->reference = 0; | 
					
						
							|  |  |  |     if(avctx->get_buffer(avctx, p) < 0){ | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-28 01:40:44 +02:00
										 |  |  |     p->pict_type = AV_PICTURE_TYPE_I; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     p->key_frame = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-31 00:34:56 +00:00
										 |  |  |     buf = buf0 + hsize; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     dsize = buf_size - hsize; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-30 20:43:07 +00:00
										 |  |  |     /* Line size in file multiple of 4 */ | 
					
						
							| 
									
										
										
										
											2011-12-15 19:23:07 +01:00
										 |  |  |     n = ((avctx->width * depth + 31) / 8) & ~3; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     if(n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8){ | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", | 
					
						
							|  |  |  |                dsize, n * avctx->height); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     // 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]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |     if(depth == 4 || depth == 8) | 
					
						
							|  |  |  |         memset(p->data[1], 0, 1024); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |     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]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |     if(avctx->pix_fmt == PIX_FMT_PAL8){ | 
					
						
							| 
									
										
										
										
											2009-09-24 05:24:46 +00:00
										 |  |  |         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; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |         buf = buf0 + 14 + ihsize; //palette location
 | 
					
						
							| 
									
										
										
										
											2009-09-24 05:24:46 +00:00
										 |  |  |         if((hsize-ihsize-14) < (colors << 2)){ // OS/2 bitmap, 3 bytes per palette entry
 | 
					
						
							|  |  |  |             for(i = 0; i < colors; i++) | 
					
						
							| 
									
										
										
										
											2011-04-27 21:49:45 +02:00
										 |  |  |                 ((uint32_t*)p->data[1])[i] = (0xff<<24) | bytestream_get_le24(&buf); | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |         }else{ | 
					
						
							| 
									
										
										
										
											2009-09-24 05:24:46 +00:00
										 |  |  |             for(i = 0; i < colors; i++) | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |                 ((uint32_t*)p->data[1])[i] = bytestream_get_le32(&buf); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         buf = buf0 + hsize; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     if(comp == BMP_RLE4 || comp == BMP_RLE8){ | 
					
						
							| 
									
										
										
										
											2009-10-01 05:46:17 +00:00
										 |  |  |         if(height < 0){ | 
					
						
							|  |  |  |             p->data[0] += p->linesize[0] * (avctx->height - 1); | 
					
						
							|  |  |  |             p->linesize[0] = -p->linesize[0]; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-02-01 14:44:51 +00:00
										 |  |  |         ff_msrle_decode(avctx, (AVPicture*)p, depth, buf, dsize); | 
					
						
							| 
									
										
										
										
											2009-10-01 05:46:17 +00:00
										 |  |  |         if(height < 0){ | 
					
						
							|  |  |  |             p->data[0] += p->linesize[0] * (avctx->height - 1); | 
					
						
							|  |  |  |             p->linesize[0] = -p->linesize[0]; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     }else{ | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |         switch(depth){ | 
					
						
							|  |  |  |         case 1: | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |             for (i = 0; i < avctx->height; i++) { | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |                 int j; | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |                 for (j = 0; j < n; j++) { | 
					
						
							| 
									
										
										
										
											2011-11-10 23:07:27 +01:00
										 |  |  |                     ptr[j*8+0] =  buf[j] >> 7; | 
					
						
							|  |  |  |                     ptr[j*8+1] = (buf[j] >> 6) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+2] = (buf[j] >> 5) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+3] = (buf[j] >> 4) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+4] = (buf[j] >> 3) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+5] = (buf[j] >> 2) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+6] = (buf[j] >> 1) & 1; | 
					
						
							|  |  |  |                     ptr[j*8+7] =  buf[j]       & 1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 buf += n; | 
					
						
							|  |  |  |                 ptr += linesize; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-03-27 16:31:47 +00:00
										 |  |  |         case 8: | 
					
						
							|  |  |  |         case 24: | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |             for(i = 0; i < avctx->height; i++){ | 
					
						
							|  |  |  |                 memcpy(ptr, buf, n); | 
					
						
							|  |  |  |                 buf += n; | 
					
						
							|  |  |  |                 ptr += linesize; | 
					
						
							| 
									
										
										
										
											2008-09-23 08:38:32 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |             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; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |                 for(j = 0; j < avctx->width; j++) | 
					
						
							| 
									
										
										
										
											2010-07-10 22:12:30 +00:00
										 |  |  |                     *dst++ = av_le2ne16(*src++); | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |                 buf += n; | 
					
						
							|  |  |  |                 ptr += linesize; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |             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]]; | 
					
						
							| 
									
										
										
										
											2011-12-02 00:21:24 +01:00
										 |  |  | /* The Microsoft documentation states:
 | 
					
						
							|  |  |  |  * "The high byte in each DWORD is not used." | 
					
						
							|  |  |  |  * Both GIMP and ImageMagick store the alpha transparency value | 
					
						
							|  |  |  |  * in the high byte for 32bit bmp files. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  |                     dst[3] = src[3]; | 
					
						
							|  |  |  |                     dst += 4; | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:46 +00:00
										 |  |  |                     src += 4; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 buf += n; | 
					
						
							|  |  |  |                 ptr += linesize; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n"); | 
					
						
							|  |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-09-23 08:45:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     *picture = s->picture; | 
					
						
							|  |  |  |     *data_size = sizeof(AVPicture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return buf_size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-21 03:11:20 +00:00
										 |  |  | static av_cold int bmp_decode_end(AVCodecContext *avctx) | 
					
						
							| 
									
										
										
										
											2007-02-01 09:48:09 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     BMPContext* c = avctx->priv_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (c->picture.data[0]) | 
					
						
							|  |  |  |         avctx->release_buffer(avctx, &c->picture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-25 21:40:11 +00:00
										 |  |  | AVCodec ff_bmp_decoder = { | 
					
						
							| 
									
										
										
										
											2011-07-17 12:54:31 +02:00
										 |  |  |     .name           = "bmp", | 
					
						
							|  |  |  |     .type           = AVMEDIA_TYPE_VIDEO, | 
					
						
							|  |  |  |     .id             = CODEC_ID_BMP, | 
					
						
							|  |  |  |     .priv_data_size = sizeof(BMPContext), | 
					
						
							|  |  |  |     .init           = bmp_decode_init, | 
					
						
							|  |  |  |     .close          = bmp_decode_end, | 
					
						
							|  |  |  |     .decode         = bmp_decode_frame, | 
					
						
							|  |  |  |     .capabilities   = CODEC_CAP_DR1, | 
					
						
							| 
									
										
										
										
											2008-06-12 21:50:13 +00:00
										 |  |  |     .long_name = NULL_IF_CONFIG_SMALL("BMP image"), | 
					
						
							| 
									
										
										
										
											2005-11-30 01:40:50 +00:00
										 |  |  | }; |