Mercurial > libavcodec.hg
annotate pcx.c @ 7352:c2318e551ff5 libavcodec
When picking a "high utility centroid" do not pick one
that has no corresponding points. Not only it is the
worst possible pick, but also the code was written
without this case in mind.
author | vitor |
---|---|
date | Wed, 23 Jul 2008 03:55:37 +0000 |
parents | e943e1409077 |
children | 54bc8a2727b0 |
rev | line source |
---|---|
6073 | 1 /* |
2 * PC Paintbrush PCX (.pcx) image decoder | |
3 * Copyright (c) 2007, 2008 Ivo van Poorten | |
4 * | |
5 * This decoder does not support CGA palettes. I am unable to find samples | |
6 * and Netpbm cannot generate them. | |
7 * | |
8 * This file is part of FFmpeg. | |
9 * | |
10 * FFmpeg is free software; you can redistribute it and/or | |
11 * modify it under the terms of the GNU Lesser General Public | |
12 * License as published by the Free Software Foundation; either | |
13 * version 2.1 of the License, or (at your option) any later version. | |
14 * | |
15 * FFmpeg is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 * Lesser General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU Lesser General Public | |
21 * License along with FFmpeg; if not, write to the Free Software | |
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
23 */ | |
24 | |
25 #include "avcodec.h" | |
26 #include "bytestream.h" | |
27 #include "bitstream.h" | |
28 | |
29 typedef struct PCXContext { | |
30 AVFrame picture; | |
31 } PCXContext; | |
32 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
33 static av_cold int pcx_init(AVCodecContext *avctx) { |
6073 | 34 PCXContext *s = avctx->priv_data; |
35 | |
36 avcodec_get_frame_defaults(&s->picture); | |
37 avctx->coded_frame= &s->picture; | |
38 | |
39 return 0; | |
40 } | |
41 | |
42 /** | |
43 * @return advanced src pointer | |
44 */ | |
6793 | 45 static const uint8_t *pcx_rle_decode(const uint8_t *src, uint8_t *dst, |
6073 | 46 unsigned int bytes_per_scanline) { |
47 unsigned int i = 0; | |
48 unsigned char run, value; | |
49 | |
50 while (i<bytes_per_scanline) { | |
51 run = 1; | |
52 value = *src++; | |
53 if (value >= 0xc0) { | |
54 run = value & 0x3f; | |
55 value = *src++; | |
56 } | |
57 while (i<bytes_per_scanline && run--) | |
58 dst[i++] = value; | |
59 } | |
60 | |
61 return src; | |
62 } | |
63 | |
6244 | 64 static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen) { |
6073 | 65 unsigned int i; |
66 | |
67 for (i=0; i<pallen; i++) | |
68 *dst++ = bytestream_get_be24(src); | |
69 memset(dst, 0, (256 - pallen) * sizeof(*dst)); | |
70 } | |
71 | |
72 static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |
6244 | 73 const uint8_t *buf, int buf_size) { |
6073 | 74 PCXContext * const s = avctx->priv_data; |
75 AVFrame *picture = data; | |
6075 | 76 AVFrame * const p = &s->picture; |
6073 | 77 int xmin, ymin, xmax, ymax; |
78 unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, | |
79 bytes_per_scanline; | |
6244 | 80 uint8_t *ptr; |
81 uint8_t const *bufstart = buf; | |
6073 | 82 |
83 if (buf[0] != 0x0a || buf[1] > 5 || buf[1] == 1 || buf[2] != 1) { | |
84 av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); | |
85 return -1; | |
86 } | |
87 | |
88 xmin = AV_RL16(buf+ 4); | |
89 ymin = AV_RL16(buf+ 6); | |
90 xmax = AV_RL16(buf+ 8); | |
91 ymax = AV_RL16(buf+10); | |
92 | |
93 if (xmax < xmin || ymax < ymin) { | |
94 av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); | |
95 return -1; | |
96 } | |
97 | |
98 w = xmax - xmin + 1; | |
99 h = ymax - ymin + 1; | |
100 | |
101 bits_per_pixel = buf[3]; | |
102 bytes_per_line = AV_RL16(buf+66); | |
103 nplanes = buf[65]; | |
104 bytes_per_scanline = nplanes * bytes_per_line; | |
105 | |
106 if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8) { | |
107 av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); | |
108 return -1; | |
109 } | |
110 | |
111 switch ((nplanes<<8) + bits_per_pixel) { | |
112 case 0x0308: | |
113 avctx->pix_fmt = PIX_FMT_RGB24; | |
114 break; | |
115 case 0x0108: | |
116 case 0x0104: | |
117 case 0x0102: | |
118 case 0x0101: | |
119 case 0x0401: | |
120 case 0x0301: | |
121 case 0x0201: | |
122 avctx->pix_fmt = PIX_FMT_PAL8; | |
123 break; | |
124 default: | |
125 av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); | |
126 return -1; | |
127 } | |
128 | |
129 buf += 128; | |
130 | |
131 if (p->data[0]) | |
132 avctx->release_buffer(avctx, p); | |
133 | |
134 if (avcodec_check_dimensions(avctx, w, h)) | |
135 return -1; | |
136 if (w != avctx->width || h != avctx->height) | |
137 avcodec_set_dimensions(avctx, w, h); | |
138 if (avctx->get_buffer(avctx, p) < 0) { | |
139 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
140 return -1; | |
141 } | |
142 | |
143 p->pict_type = FF_I_TYPE; | |
144 | |
145 ptr = p->data[0]; | |
146 stride = p->linesize[0]; | |
147 | |
148 if (nplanes == 3 && bits_per_pixel == 8) { | |
149 uint8_t scanline[bytes_per_scanline]; | |
150 | |
151 for (y=0; y<h; y++) { | |
152 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
153 | |
154 for (x=0; x<w; x++) { | |
155 ptr[3*x ] = scanline[x ]; | |
156 ptr[3*x+1] = scanline[x+ bytes_per_line ]; | |
157 ptr[3*x+2] = scanline[x+(bytes_per_line<<1)]; | |
158 } | |
159 | |
160 ptr += stride; | |
161 } | |
162 | |
163 } else if (nplanes == 1 && bits_per_pixel == 8) { | |
164 uint8_t scanline[bytes_per_scanline]; | |
6244 | 165 const uint8_t *palstart = bufstart + buf_size - 769; |
6073 | 166 |
167 for (y=0; y<h; y++, ptr+=stride) { | |
168 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
169 memcpy(ptr, scanline, w); | |
170 } | |
171 | |
172 if (buf != palstart) { | |
173 av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n"); | |
174 buf = palstart; | |
175 } | |
176 if (*buf++ != 12) { | |
177 av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n"); | |
178 return -1; | |
179 } | |
180 | |
181 } else if (nplanes == 1) { /* all packed formats, max. 16 colors */ | |
182 uint8_t scanline[bytes_per_scanline]; | |
183 GetBitContext s; | |
184 | |
185 for (y=0; y<h; y++) { | |
186 init_get_bits(&s, scanline, bytes_per_scanline<<3); | |
187 | |
188 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
189 | |
190 for (x=0; x<w; x++) | |
191 ptr[x] = get_bits(&s, bits_per_pixel); | |
192 ptr += stride; | |
193 } | |
194 | |
195 } else { /* planar, 4, 8 or 16 colors */ | |
196 uint8_t scanline[bytes_per_scanline]; | |
197 int i; | |
198 | |
199 for (y=0; y<h; y++) { | |
200 buf = pcx_rle_decode(buf, scanline, bytes_per_scanline); | |
201 | |
202 for (x=0; x<w; x++) { | |
203 int m = 0x80 >> (x&7), v = 0; | |
204 for (i=nplanes - 1; i>=0; i--) { | |
205 v <<= 1; | |
206 v += !!(scanline[i*bytes_per_line + (x>>3)] & m); | |
207 } | |
208 ptr[x] = v; | |
209 } | |
210 ptr += stride; | |
211 } | |
212 } | |
213 | |
214 if (nplanes == 1 && bits_per_pixel == 8) { | |
215 pcx_palette(&buf, (uint32_t *) p->data[1], 256); | |
216 } else if (bits_per_pixel < 8) { | |
6244 | 217 const uint8_t *palette = bufstart+16; |
6073 | 218 pcx_palette(&palette, (uint32_t *) p->data[1], 16); |
219 } | |
220 | |
221 *picture = s->picture; | |
222 *data_size = sizeof(AVFrame); | |
223 | |
224 return buf - bufstart; | |
225 } | |
226 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6244
diff
changeset
|
227 static av_cold int pcx_end(AVCodecContext *avctx) { |
6073 | 228 PCXContext *s = avctx->priv_data; |
229 | |
230 if(s->picture.data[0]) | |
231 avctx->release_buffer(avctx, &s->picture); | |
232 | |
233 return 0; | |
234 } | |
235 | |
236 AVCodec pcx_decoder = { | |
237 "pcx", | |
238 CODEC_TYPE_VIDEO, | |
239 CODEC_ID_PCX, | |
240 sizeof(PCXContext), | |
241 pcx_init, | |
242 NULL, | |
243 pcx_end, | |
244 pcx_decode_frame, | |
245 0, | |
6722 | 246 NULL, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6793
diff
changeset
|
247 .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), |
6073 | 248 }; |