3 * Copyright (c) 2002, 2003 Fabrice Bellard.
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 static inline int pnm_space(int c)
25 return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
28 static void pnm_get(ByteIOContext *f, char *str, int buf_size)
33 /* skip spaces and comments */
39 } while (c != '\n' && c != URL_EOF);
40 } else if (!pnm_space(c)) {
46 while (c != URL_EOF && !pnm_space(c)) {
47 if ((s - str) < buf_size - 1)
54 static int pnm_read1(ByteIOContext *f,
55 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
58 int i, n, linesize, h;
61 AVImageInfo info1, *info = &info1;
64 pnm_get(f, buf1, sizeof(buf1));
65 if (!strcmp(buf1, "P4")) {
66 info->pix_fmt = PIX_FMT_MONOWHITE;
67 } else if (!strcmp(buf1, "P5")) {
69 info->pix_fmt = PIX_FMT_YUV420P;
71 info->pix_fmt = PIX_FMT_GRAY8;
72 } else if (!strcmp(buf1, "P6")) {
73 info->pix_fmt = PIX_FMT_RGB24;
75 return AVERROR_INVALIDDATA;
77 pnm_get(f, buf1, sizeof(buf1));
78 info->width = atoi(buf1);
80 return AVERROR_INVALIDDATA;
81 pnm_get(f, buf1, sizeof(buf1));
82 info->height = atoi(buf1);
83 if (info->height <= 0)
84 return AVERROR_INVALIDDATA;
85 if (info->pix_fmt != PIX_FMT_MONOWHITE) {
86 pnm_get(f, buf1, sizeof(buf1));
89 /* more check if YUV420 */
90 if (info->pix_fmt == PIX_FMT_YUV420P) {
91 if ((info->width & 1) != 0)
92 return AVERROR_INVALIDDATA;
93 h = (info->height * 2);
95 return AVERROR_INVALIDDATA;
100 ret = alloc_cb(opaque, info);
104 switch(info->pix_fmt) {
106 return AVERROR_INVALIDDATA;
113 case PIX_FMT_MONOWHITE:
114 n = (info->width + 7) >> 3;
116 ptr = info->pict.data[0];
117 linesize = info->pict.linesize[0];
118 for(i = 0; i < info->height; i++) {
119 get_buffer(f, ptr, n);
123 case PIX_FMT_YUV420P:
125 unsigned char *ptr1, *ptr2;
128 ptr = info->pict.data[0];
129 linesize = info->pict.linesize[0];
130 for(i = 0; i < info->height; i++) {
131 get_buffer(f, ptr, n);
134 ptr1 = info->pict.data[1];
135 ptr2 = info->pict.data[2];
137 h = info->height >> 1;
138 for(i = 0; i < h; i++) {
139 get_buffer(f, ptr1, n);
140 get_buffer(f, ptr2, n);
141 ptr1 += info->pict.linesize[1];
142 ptr2 += info->pict.linesize[2];
150 static int pnm_read(ByteIOContext *f,
151 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
153 return pnm_read1(f, alloc_cb, opaque, 0);
156 static int pgmyuv_read(ByteIOContext *f,
157 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
159 return pnm_read1(f, alloc_cb, opaque, 1);
162 static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
164 int i, h, h1, c, n, linesize;
166 uint8_t *ptr, *ptr1, *ptr2;
170 switch(info->pix_fmt) {
171 case PIX_FMT_MONOWHITE:
173 n = (info->width + 7) >> 3;
183 case PIX_FMT_YUV420P:
189 return AVERROR_INVALIDDATA;
191 snprintf(buf, sizeof(buf),
194 put_buffer(pb, buf, strlen(buf));
195 if (info->pix_fmt != PIX_FMT_MONOWHITE) {
196 snprintf(buf, sizeof(buf),
198 put_buffer(pb, buf, strlen(buf));
201 ptr = info->pict.data[0];
202 linesize = info->pict.linesize[0];
204 put_buffer(pb, ptr, n);
208 if (info->pix_fmt == PIX_FMT_YUV420P) {
211 ptr1 = info->pict.data[1];
212 ptr2 = info->pict.data[2];
214 put_buffer(pb, ptr1, n);
215 put_buffer(pb, ptr2, n);
216 ptr1 += info->pict.linesize[1];
217 ptr2 += info->pict.linesize[2];
220 put_flush_packet(pb);
224 static int pam_read(ByteIOContext *f,
225 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
227 int i, n, linesize, h, w, depth, maxval;
228 char buf1[32], tuple_type[32];
230 AVImageInfo info1, *info = &info1;
233 pnm_get(f, buf1, sizeof(buf1));
234 if (strcmp(buf1, "P7") != 0)
235 return AVERROR_INVALIDDATA;
240 tuple_type[0] = '\0';
242 pnm_get(f, buf1, sizeof(buf1));
243 if (!strcmp(buf1, "WIDTH")) {
244 pnm_get(f, buf1, sizeof(buf1));
245 w = strtol(buf1, NULL, 10);
246 } else if (!strcmp(buf1, "HEIGHT")) {
247 pnm_get(f, buf1, sizeof(buf1));
248 h = strtol(buf1, NULL, 10);
249 } else if (!strcmp(buf1, "DEPTH")) {
250 pnm_get(f, buf1, sizeof(buf1));
251 depth = strtol(buf1, NULL, 10);
252 } else if (!strcmp(buf1, "MAXVAL")) {
253 pnm_get(f, buf1, sizeof(buf1));
254 maxval = strtol(buf1, NULL, 10);
255 } else if (!strcmp(buf1, "TUPLETYPE")) {
256 pnm_get(f, buf1, sizeof(buf1));
257 pstrcpy(tuple_type, sizeof(tuple_type), buf1);
258 } else if (!strcmp(buf1, "ENDHDR")) {
261 return AVERROR_INVALIDDATA;
264 /* check that all tags are present */
265 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0')
266 return AVERROR_INVALIDDATA;
271 info->pix_fmt = PIX_FMT_MONOWHITE;
273 info->pix_fmt = PIX_FMT_GRAY8;
274 } else if (depth == 3) {
275 info->pix_fmt = PIX_FMT_RGB24;
276 } else if (depth == 4) {
277 info->pix_fmt = PIX_FMT_RGBA32;
279 return AVERROR_INVALIDDATA;
281 ret = alloc_cb(opaque, info);
285 switch(info->pix_fmt) {
287 return AVERROR_INVALIDDATA;
294 case PIX_FMT_MONOWHITE:
295 n = (info->width + 7) >> 3;
297 ptr = info->pict.data[0];
298 linesize = info->pict.linesize[0];
299 for(i = 0; i < info->height; i++) {
300 get_buffer(f, ptr, n);
305 ptr = info->pict.data[0];
306 linesize = info->pict.linesize[0];
307 for(i = 0; i < info->height; i++) {
310 for(j = 0;j < w; j++) {
315 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
324 static int pam_write(ByteIOContext *pb, AVImageInfo *info)
326 int i, h, w, n, linesize, depth, maxval;
327 const char *tuple_type;
333 switch(info->pix_fmt) {
334 case PIX_FMT_MONOWHITE:
335 n = (info->width + 7) >> 3;
338 tuple_type = "BLACKANDWHITE";
344 tuple_type = "GRAYSCALE";
356 tuple_type = "RGB_ALPHA";
359 return AVERROR_INVALIDDATA;
361 snprintf(buf, sizeof(buf),
362 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
363 w, h, depth, maxval, tuple_type);
364 put_buffer(pb, buf, strlen(buf));
366 ptr = info->pict.data[0];
367 linesize = info->pict.linesize[0];
369 if (info->pix_fmt == PIX_FMT_RGBA32) {
375 v = ((uint32_t *)ptr)[j];
376 put_byte(pb, (v >> 16) & 0xff);
377 put_byte(pb, (v >> 8) & 0xff);
378 put_byte(pb, (v) & 0xff);
379 put_byte(pb, (v >> 24) & 0xff);
385 put_buffer(pb, ptr, n);
389 put_flush_packet(pb);
393 static int pnm_probe(AVProbeData *pd)
395 const char *p = pd->buf;
396 if (pd->buf_size >= 8 &&
398 p[1] >= '4' && p[1] <= '6' &&
400 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
405 static int pgmyuv_probe(AVProbeData *pd)
407 if (match_ext(pd->filename, "pgmyuv"))
408 return AVPROBE_SCORE_MAX;
413 static int pam_probe(AVProbeData *pd)
415 const char *p = pd->buf;
416 if (pd->buf_size >= 8 &&
420 return AVPROBE_SCORE_MAX;
425 AVImageFormat pnm_image_format = {
434 AVImageFormat pbm_image_format = {
439 (1 << PIX_FMT_MONOWHITE),
443 AVImageFormat pgm_image_format = {
448 (1 << PIX_FMT_GRAY8),
452 AVImageFormat ppm_image_format = {
457 (1 << PIX_FMT_RGB24),
461 AVImageFormat pam_image_format = {
466 (1 << PIX_FMT_MONOWHITE) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) |
467 (1 << PIX_FMT_RGBA32),
471 AVImageFormat pgmyuv_image_format = {
476 (1 << PIX_FMT_YUV420P),