ffmpeg / libavcodec / bmp.c @ 5509bffa
History | View | Annotate | Download (6.27 KB)
1 |
/*
|
---|---|
2 |
* BMP image format
|
3 |
* Copyright (c) 2005 Mans Rullgard
|
4 |
*
|
5 |
* This library is free software; you can redistribute it and/or
|
6 |
* modify it under the terms of the GNU Lesser General Public
|
7 |
* License as published by the Free Software Foundation; either
|
8 |
* version 2 of the License, or (at your option) any later version.
|
9 |
*
|
10 |
* This library is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13 |
* Lesser General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU Lesser General Public
|
16 |
* License along with this library; if not, write to the Free Software
|
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 |
*/
|
19 |
|
20 |
#include "avcodec.h" |
21 |
#include "bitstream.h" |
22 |
#include "bswap.h" |
23 |
|
24 |
typedef struct BMPContext { |
25 |
AVFrame picture; |
26 |
} BMPContext; |
27 |
|
28 |
#define BMP_RGB 0 |
29 |
#define BMP_RLE8 1 |
30 |
#define BMP_RLE4 2 |
31 |
#define BMP_BITFIELDS 3 |
32 |
|
33 |
#define read16(bits) bswap_16(get_bits(bits, 16)) |
34 |
#define read32(bits) bswap_32(get_bits_long(bits, 32)) |
35 |
|
36 |
static int bmp_decode_init(AVCodecContext *avctx){ |
37 |
BMPContext *s = avctx->priv_data; |
38 |
|
39 |
avcodec_get_frame_defaults((AVFrame*)&s->picture); |
40 |
avctx->coded_frame = (AVFrame*)&s->picture; |
41 |
|
42 |
return 0; |
43 |
} |
44 |
|
45 |
static int bmp_decode_frame(AVCodecContext *avctx, |
46 |
void *data, int *data_size, |
47 |
uint8_t *buf, int buf_size)
|
48 |
{ |
49 |
BMPContext *s = avctx->priv_data; |
50 |
AVFrame *picture = data; |
51 |
AVFrame *p = &s->picture; |
52 |
GetBitContext bits; |
53 |
unsigned int fsize, hsize; |
54 |
int width, height;
|
55 |
unsigned int depth; |
56 |
unsigned int comp; |
57 |
unsigned int ihsize; |
58 |
int i, j, n, linesize;
|
59 |
uint32_t rgb[3];
|
60 |
uint8_t *ptr; |
61 |
int dsize;
|
62 |
|
63 |
if(buf_size < 14){ |
64 |
av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
|
65 |
return -1; |
66 |
} |
67 |
|
68 |
init_get_bits(&bits, buf, buf_size); |
69 |
|
70 |
if(get_bits(&bits, 16) != 0x424d){ /* 'BM' */ |
71 |
av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
|
72 |
return -1; |
73 |
} |
74 |
|
75 |
fsize = read32(&bits); |
76 |
if(buf_size < fsize){
|
77 |
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
78 |
buf_size, fsize); |
79 |
return -1; |
80 |
} |
81 |
|
82 |
skip_bits(&bits, 16); /* reserved1 */ |
83 |
skip_bits(&bits, 16); /* reserved2 */ |
84 |
|
85 |
hsize = read32(&bits); /* header size */
|
86 |
if(fsize <= hsize){
|
87 |
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
88 |
fsize, hsize); |
89 |
return -1; |
90 |
} |
91 |
|
92 |
ihsize = read32(&bits); /* more header size */
|
93 |
if(ihsize + 14 > hsize){ |
94 |
av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
|
95 |
return -1; |
96 |
} |
97 |
|
98 |
width = read32(&bits); |
99 |
height = read32(&bits); |
100 |
|
101 |
if(read16(&bits) != 1){ /* planes */ |
102 |
av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
|
103 |
return -1; |
104 |
} |
105 |
|
106 |
depth = read16(&bits); |
107 |
|
108 |
if(ihsize > 16) |
109 |
comp = read32(&bits); |
110 |
else
|
111 |
comp = BMP_RGB; |
112 |
|
113 |
if(comp != BMP_RGB && comp != BMP_BITFIELDS){
|
114 |
av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
|
115 |
return -1; |
116 |
} |
117 |
|
118 |
if(comp == BMP_BITFIELDS){
|
119 |
skip_bits(&bits, 20 * 8); |
120 |
rgb[0] = read32(&bits);
|
121 |
rgb[1] = read32(&bits);
|
122 |
rgb[2] = read32(&bits);
|
123 |
} |
124 |
|
125 |
avctx->codec_id = CODEC_ID_BMP; |
126 |
avctx->width = width; |
127 |
avctx->height = height > 0? height: -height;
|
128 |
|
129 |
avctx->pix_fmt = PIX_FMT_NONE; |
130 |
|
131 |
switch(depth){
|
132 |
case 32: |
133 |
if(comp == BMP_BITFIELDS){
|
134 |
rgb[0] = (rgb[0] >> 15) & 3; |
135 |
rgb[1] = (rgb[1] >> 15) & 3; |
136 |
rgb[2] = (rgb[2] >> 15) & 3; |
137 |
|
138 |
if(rgb[0] + rgb[1] + rgb[2] != 3 || |
139 |
rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){ |
140 |
break;
|
141 |
} |
142 |
} else {
|
143 |
rgb[0] = 2; |
144 |
rgb[1] = 1; |
145 |
rgb[2] = 0; |
146 |
} |
147 |
|
148 |
avctx->pix_fmt = PIX_FMT_BGR24; |
149 |
break;
|
150 |
case 24: |
151 |
avctx->pix_fmt = PIX_FMT_BGR24; |
152 |
break;
|
153 |
case 16: |
154 |
if(comp == BMP_RGB)
|
155 |
avctx->pix_fmt = PIX_FMT_RGB555; |
156 |
break;
|
157 |
default:
|
158 |
av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
|
159 |
return -1; |
160 |
} |
161 |
|
162 |
if(avctx->pix_fmt == PIX_FMT_NONE){
|
163 |
av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
|
164 |
return -1; |
165 |
} |
166 |
|
167 |
p->reference = 0;
|
168 |
if(avctx->get_buffer(avctx, p) < 0){ |
169 |
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
170 |
return -1; |
171 |
} |
172 |
p->pict_type = FF_I_TYPE; |
173 |
p->key_frame = 1;
|
174 |
|
175 |
buf += hsize; |
176 |
dsize = buf_size - hsize; |
177 |
|
178 |
n = avctx->width * (depth / 8);
|
179 |
|
180 |
if(n * avctx->height > dsize){
|
181 |
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
|
182 |
dsize, n * avctx->height); |
183 |
return -1; |
184 |
} |
185 |
|
186 |
if(height > 0){ |
187 |
ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; |
188 |
linesize = -p->linesize[0];
|
189 |
} else {
|
190 |
ptr = p->data[0];
|
191 |
linesize = p->linesize[0];
|
192 |
} |
193 |
|
194 |
switch(depth){
|
195 |
case 24: |
196 |
for(i = 0; i < avctx->height; i++){ |
197 |
memcpy(ptr, buf, n); |
198 |
buf += n; |
199 |
ptr += linesize; |
200 |
} |
201 |
break;
|
202 |
case 16: |
203 |
for(i = 0; i < avctx->height; i++){ |
204 |
uint16_t *src = (uint16_t *) buf; |
205 |
uint16_t *dst = (uint16_t *) ptr; |
206 |
|
207 |
for(j = 0; j < avctx->width; j++) |
208 |
*dst++ = le2me_16(*src++); |
209 |
|
210 |
buf += n; |
211 |
ptr += linesize; |
212 |
} |
213 |
break;
|
214 |
case 32: |
215 |
for(i = 0; i < avctx->height; i++){ |
216 |
uint8_t *src = buf; |
217 |
uint8_t *dst = ptr; |
218 |
|
219 |
for(j = 0; j < avctx->width; j++){ |
220 |
dst[0] = src[rgb[2]]; |
221 |
dst[1] = src[rgb[1]]; |
222 |
dst[2] = src[rgb[0]]; |
223 |
dst += 3;
|
224 |
src += 4;
|
225 |
} |
226 |
|
227 |
buf += n; |
228 |
ptr += linesize; |
229 |
} |
230 |
break;
|
231 |
default:
|
232 |
av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");
|
233 |
return -1; |
234 |
} |
235 |
|
236 |
*picture = s->picture; |
237 |
*data_size = sizeof(AVPicture);
|
238 |
|
239 |
return buf_size;
|
240 |
} |
241 |
|
242 |
AVCodec bmp_decoder = { |
243 |
"bmp",
|
244 |
CODEC_TYPE_VIDEO, |
245 |
CODEC_ID_BMP, |
246 |
sizeof(BMPContext),
|
247 |
bmp_decode_init, |
248 |
NULL,
|
249 |
NULL,
|
250 |
bmp_decode_frame |
251 |
}; |