VirtualBox

source: vbox/trunk/src/libs/ffmpeg-20060710/libavformat/pnm.c@ 7692

Last change on this file since 7692 was 5776, checked in by vboxsync, 17 years ago

ffmpeg: exported to OSE

File size: 11.9 KB
Line 
1/*
2 * PNM image format
3 * Copyright (c) 2002, 2003 Fabrice Bellard.
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#include "avformat.h"
20
21static inline int pnm_space(int c)
22{
23 return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
24}
25
26static void pnm_get(ByteIOContext *f, char *str, int buf_size)
27{
28 char *s;
29 int c;
30
31 /* skip spaces and comments */
32 for(;;) {
33 c = url_fgetc(f);
34 if (c == '#') {
35 do {
36 c = url_fgetc(f);
37 } while (c != '\n' && c != URL_EOF);
38 } else if (!pnm_space(c)) {
39 break;
40 }
41 }
42
43 s = str;
44 while (c != URL_EOF && !pnm_space(c)) {
45 if ((s - str) < buf_size - 1)
46 *s++ = c;
47 c = url_fgetc(f);
48 }
49 *s = '\0';
50}
51
52static int pnm_read1(ByteIOContext *f,
53 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
54 int allow_yuv)
55{
56 int i, n, linesize, h;
57 char buf1[32];
58 unsigned char *ptr;
59 AVImageInfo info1, *info = &info1;
60 int ret;
61
62 pnm_get(f, buf1, sizeof(buf1));
63 if (!strcmp(buf1, "P4")) {
64 info->pix_fmt = PIX_FMT_MONOWHITE;
65 } else if (!strcmp(buf1, "P5")) {
66 if (allow_yuv)
67 info->pix_fmt = PIX_FMT_YUV420P;
68 else
69 info->pix_fmt = PIX_FMT_GRAY8;
70 } else if (!strcmp(buf1, "P6")) {
71 info->pix_fmt = PIX_FMT_RGB24;
72 } else {
73 return AVERROR_INVALIDDATA;
74 }
75 pnm_get(f, buf1, sizeof(buf1));
76 info->width = atoi(buf1);
77 if (info->width <= 0)
78 return AVERROR_INVALIDDATA;
79 pnm_get(f, buf1, sizeof(buf1));
80 info->height = atoi(buf1);
81 if (info->height <= 0)
82 return AVERROR_INVALIDDATA;
83 if (info->pix_fmt != PIX_FMT_MONOWHITE) {
84 pnm_get(f, buf1, sizeof(buf1));
85 }
86
87 /* more check if YUV420 */
88 if (info->pix_fmt == PIX_FMT_YUV420P) {
89 if ((info->width & 1) != 0)
90 return AVERROR_INVALIDDATA;
91 h = (info->height * 2);
92 if ((h % 3) != 0)
93 return AVERROR_INVALIDDATA;
94 h /= 3;
95 info->height = h;
96 }
97
98 ret = alloc_cb(opaque, info);
99 if (ret)
100 return ret;
101
102 switch(info->pix_fmt) {
103 default:
104 return AVERROR_INVALIDDATA;
105 case PIX_FMT_RGB24:
106 n = info->width * 3;
107 goto do_read;
108 case PIX_FMT_GRAY8:
109 n = info->width;
110 goto do_read;
111 case PIX_FMT_MONOWHITE:
112 n = (info->width + 7) >> 3;
113 do_read:
114 ptr = info->pict.data[0];
115 linesize = info->pict.linesize[0];
116 for(i = 0; i < info->height; i++) {
117 get_buffer(f, ptr, n);
118 ptr += linesize;
119 }
120 break;
121 case PIX_FMT_YUV420P:
122 {
123 unsigned char *ptr1, *ptr2;
124
125 n = info->width;
126 ptr = info->pict.data[0];
127 linesize = info->pict.linesize[0];
128 for(i = 0; i < info->height; i++) {
129 get_buffer(f, ptr, n);
130 ptr += linesize;
131 }
132 ptr1 = info->pict.data[1];
133 ptr2 = info->pict.data[2];
134 n >>= 1;
135 h = info->height >> 1;
136 for(i = 0; i < h; i++) {
137 get_buffer(f, ptr1, n);
138 get_buffer(f, ptr2, n);
139 ptr1 += info->pict.linesize[1];
140 ptr2 += info->pict.linesize[2];
141 }
142 }
143 break;
144 }
145 return 0;
146}
147
148static int pnm_read(ByteIOContext *f,
149 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
150{
151 return pnm_read1(f, alloc_cb, opaque, 0);
152}
153
154static int pgmyuv_read(ByteIOContext *f,
155 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
156{
157 return pnm_read1(f, alloc_cb, opaque, 1);
158}
159
160static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
161{
162 int i, h, h1, c, n, linesize;
163 char buf[100];
164 uint8_t *ptr, *ptr1, *ptr2;
165
166 h = info->height;
167 h1 = h;
168 switch(info->pix_fmt) {
169 case PIX_FMT_MONOWHITE:
170 c = '4';
171 n = (info->width + 7) >> 3;
172 break;
173 case PIX_FMT_GRAY8:
174 c = '5';
175 n = info->width;
176 break;
177 case PIX_FMT_RGB24:
178 c = '6';
179 n = info->width * 3;
180 break;
181 case PIX_FMT_YUV420P:
182 c = '5';
183 n = info->width;
184 h1 = (h * 3) / 2;
185 break;
186 default:
187 return AVERROR_INVALIDDATA;
188 }
189 snprintf(buf, sizeof(buf),
190 "P%c\n%d %d\n",
191 c, info->width, h1);
192 put_buffer(pb, buf, strlen(buf));
193 if (info->pix_fmt != PIX_FMT_MONOWHITE) {
194 snprintf(buf, sizeof(buf),
195 "%d\n", 255);
196 put_buffer(pb, buf, strlen(buf));
197 }
198
199 ptr = info->pict.data[0];
200 linesize = info->pict.linesize[0];
201 for(i=0;i<h;i++) {
202 put_buffer(pb, ptr, n);
203 ptr += linesize;
204 }
205
206 if (info->pix_fmt == PIX_FMT_YUV420P) {
207 h >>= 1;
208 n >>= 1;
209 ptr1 = info->pict.data[1];
210 ptr2 = info->pict.data[2];
211 for(i=0;i<h;i++) {
212 put_buffer(pb, ptr1, n);
213 put_buffer(pb, ptr2, n);
214 ptr1 += info->pict.linesize[1];
215 ptr2 += info->pict.linesize[2];
216 }
217 }
218 put_flush_packet(pb);
219 return 0;
220}
221
222static int pam_read(ByteIOContext *f,
223 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
224{
225 int i, n, linesize, h, w, depth, maxval;
226 char buf1[32], tuple_type[32];
227 unsigned char *ptr;
228 AVImageInfo info1, *info = &info1;
229 int ret;
230
231 pnm_get(f, buf1, sizeof(buf1));
232 if (strcmp(buf1, "P7") != 0)
233 return AVERROR_INVALIDDATA;
234 w = -1;
235 h = -1;
236 maxval = -1;
237 depth = -1;
238 tuple_type[0] = '\0';
239 for(;;) {
240 pnm_get(f, buf1, sizeof(buf1));
241 if (!strcmp(buf1, "WIDTH")) {
242 pnm_get(f, buf1, sizeof(buf1));
243 w = strtol(buf1, NULL, 10);
244 } else if (!strcmp(buf1, "HEIGHT")) {
245 pnm_get(f, buf1, sizeof(buf1));
246 h = strtol(buf1, NULL, 10);
247 } else if (!strcmp(buf1, "DEPTH")) {
248 pnm_get(f, buf1, sizeof(buf1));
249 depth = strtol(buf1, NULL, 10);
250 } else if (!strcmp(buf1, "MAXVAL")) {
251 pnm_get(f, buf1, sizeof(buf1));
252 maxval = strtol(buf1, NULL, 10);
253 } else if (!strcmp(buf1, "TUPLETYPE")) {
254 pnm_get(f, buf1, sizeof(buf1));
255 pstrcpy(tuple_type, sizeof(tuple_type), buf1);
256 } else if (!strcmp(buf1, "ENDHDR")) {
257 break;
258 } else {
259 return AVERROR_INVALIDDATA;
260 }
261 }
262 /* check that all tags are present */
263 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0')
264 return AVERROR_INVALIDDATA;
265 info->width = w;
266 info->height = h;
267 if (depth == 1) {
268 if (maxval == 1)
269 info->pix_fmt = PIX_FMT_MONOWHITE;
270 else
271 info->pix_fmt = PIX_FMT_GRAY8;
272 } else if (depth == 3) {
273 info->pix_fmt = PIX_FMT_RGB24;
274 } else if (depth == 4) {
275 info->pix_fmt = PIX_FMT_RGBA32;
276 } else {
277 return AVERROR_INVALIDDATA;
278 }
279 ret = alloc_cb(opaque, info);
280 if (ret)
281 return ret;
282
283 switch(info->pix_fmt) {
284 default:
285 return AVERROR_INVALIDDATA;
286 case PIX_FMT_RGB24:
287 n = info->width * 3;
288 goto do_read;
289 case PIX_FMT_GRAY8:
290 n = info->width;
291 goto do_read;
292 case PIX_FMT_MONOWHITE:
293 n = (info->width + 7) >> 3;
294 do_read:
295 ptr = info->pict.data[0];
296 linesize = info->pict.linesize[0];
297 for(i = 0; i < info->height; i++) {
298 get_buffer(f, ptr, n);
299 ptr += linesize;
300 }
301 break;
302 case PIX_FMT_RGBA32:
303 ptr = info->pict.data[0];
304 linesize = info->pict.linesize[0];
305 for(i = 0; i < info->height; i++) {
306 int j, r, g, b, a;
307
308 for(j = 0;j < w; j++) {
309 r = get_byte(f);
310 g = get_byte(f);
311 b = get_byte(f);
312 a = get_byte(f);
313 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
314 }
315 ptr += linesize;
316 }
317 break;
318 }
319 return 0;
320}
321
322static int pam_write(ByteIOContext *pb, AVImageInfo *info)
323{
324 int i, h, w, n, linesize, depth, maxval;
325 const char *tuple_type;
326 char buf[100];
327 uint8_t *ptr;
328
329 h = info->height;
330 w = info->width;
331 switch(info->pix_fmt) {
332 case PIX_FMT_MONOWHITE:
333 n = (info->width + 7) >> 3;
334 depth = 1;
335 maxval = 1;
336 tuple_type = "BLACKANDWHITE";
337 break;
338 case PIX_FMT_GRAY8:
339 n = info->width;
340 depth = 1;
341 maxval = 255;
342 tuple_type = "GRAYSCALE";
343 break;
344 case PIX_FMT_RGB24:
345 n = info->width * 3;
346 depth = 3;
347 maxval = 255;
348 tuple_type = "RGB";
349 break;
350 case PIX_FMT_RGBA32:
351 n = info->width * 4;
352 depth = 4;
353 maxval = 255;
354 tuple_type = "RGB_ALPHA";
355 break;
356 default:
357 return AVERROR_INVALIDDATA;
358 }
359 snprintf(buf, sizeof(buf),
360 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
361 w, h, depth, maxval, tuple_type);
362 put_buffer(pb, buf, strlen(buf));
363
364 ptr = info->pict.data[0];
365 linesize = info->pict.linesize[0];
366
367 if (info->pix_fmt == PIX_FMT_RGBA32) {
368 int j;
369 unsigned int v;
370
371 for(i=0;i<h;i++) {
372 for(j=0;j<w;j++) {
373 v = ((uint32_t *)ptr)[j];
374 put_byte(pb, (v >> 16) & 0xff);
375 put_byte(pb, (v >> 8) & 0xff);
376 put_byte(pb, (v) & 0xff);
377 put_byte(pb, (v >> 24) & 0xff);
378 }
379 ptr += linesize;
380 }
381 } else {
382 for(i=0;i<h;i++) {
383 put_buffer(pb, ptr, n);
384 ptr += linesize;
385 }
386 }
387 put_flush_packet(pb);
388 return 0;
389}
390
391static int pnm_probe(AVProbeData *pd)
392{
393 const char *p = pd->buf;
394 if (pd->buf_size >= 8 &&
395 p[0] == 'P' &&
396 p[1] >= '4' && p[1] <= '6' &&
397 pnm_space(p[2]) )
398 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
399 else
400 return 0;
401}
402
403static int pgmyuv_probe(AVProbeData *pd)
404{
405 if (match_ext(pd->filename, "pgmyuv"))
406 return AVPROBE_SCORE_MAX;
407 else
408 return 0;
409}
410
411static int pam_probe(AVProbeData *pd)
412{
413 const char *p = pd->buf;
414 if (pd->buf_size >= 8 &&
415 p[0] == 'P' &&
416 p[1] == '7' &&
417 p[2] == '\n')
418 return AVPROBE_SCORE_MAX;
419 else
420 return 0;
421}
422
423AVImageFormat pnm_image_format = {
424 "pnm",
425 NULL,
426 pnm_probe,
427 pnm_read,
428 0,
429 NULL,
430};
431
432AVImageFormat pbm_image_format = {
433 "pbm",
434 "pbm",
435 NULL,
436 NULL,
437 (1 << PIX_FMT_MONOWHITE),
438 pnm_write,
439};
440
441AVImageFormat pgm_image_format = {
442 "pgm",
443 "pgm",
444 NULL,
445 NULL,
446 (1 << PIX_FMT_GRAY8),
447 pnm_write,
448};
449
450AVImageFormat ppm_image_format = {
451 "ppm",
452 "ppm",
453 NULL,
454 NULL,
455 (1 << PIX_FMT_RGB24),
456 pnm_write,
457};
458
459AVImageFormat pam_image_format = {
460 "pam",
461 "pam",
462 pam_probe,
463 pam_read,
464 (1 << PIX_FMT_MONOWHITE) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) |
465 (1 << PIX_FMT_RGBA32),
466 pam_write,
467};
468
469AVImageFormat pgmyuv_image_format = {
470 "pgmyuv",
471 "pgmyuv",
472 pgmyuv_probe,
473 pgmyuv_read,
474 (1 << PIX_FMT_YUV420P),
475 pnm_write,
476};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette