3 * Copyright (c) 2002, 2003 Fabrice Bellard.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 static inline int pnm_space(int c)
23 return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
26 static void pnm_get(ByteIOContext *f, char *str, int buf_size)
31 /* skip spaces and comments */
37 } while (c != '\n' && c != URL_EOF);
38 } else if (!pnm_space(c)) {
44 while (c != URL_EOF && !pnm_space(c)) {
45 if ((s - str) < buf_size - 1)
52 static int pnm_read1(ByteIOContext *f,
53 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
56 int i, n, linesize, h;
59 AVImageInfo info1, *info = &info1;
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")) {
67 info->pix_fmt = PIX_FMT_YUV420P;
69 info->pix_fmt = PIX_FMT_GRAY8;
70 } else if (!strcmp(buf1, "P6")) {
71 info->pix_fmt = PIX_FMT_RGB24;
73 return AVERROR_INVALIDDATA;
75 pnm_get(f, buf1, sizeof(buf1));
76 info->width = atoi(buf1);
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));
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);
93 return AVERROR_INVALIDDATA;
98 ret = alloc_cb(opaque, info);
102 switch(info->pix_fmt) {
104 return AVERROR_INVALIDDATA;
111 case PIX_FMT_MONOWHITE:
112 n = (info->width + 7) >> 3;
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);
121 case PIX_FMT_YUV420P:
123 unsigned char *ptr1, *ptr2;
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);
132 ptr1 = info->pict.data[1];
133 ptr2 = info->pict.data[2];
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];
148 static int pnm_read(ByteIOContext *f,
149 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
151 return pnm_read1(f, alloc_cb, opaque, 0);
154 static int pgmyuv_read(ByteIOContext *f,
155 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
157 return pnm_read1(f, alloc_cb, opaque, 1);
160 static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
162 int i, h, h1, c, n, linesize;
164 uint8_t *ptr, *ptr1, *ptr2;
168 switch(info->pix_fmt) {
169 case PIX_FMT_MONOWHITE:
171 n = (info->width + 7) >> 3;
181 case PIX_FMT_YUV420P:
187 return AVERROR_INVALIDDATA;
189 snprintf(buf, sizeof(buf),
192 put_buffer(pb, buf, strlen(buf));
193 if (info->pix_fmt != PIX_FMT_MONOWHITE) {
194 snprintf(buf, sizeof(buf),
196 put_buffer(pb, buf, strlen(buf));
199 ptr = info->pict.data[0];
200 linesize = info->pict.linesize[0];
202 put_buffer(pb, ptr, n);
206 if (info->pix_fmt == PIX_FMT_YUV420P) {
209 ptr1 = info->pict.data[1];
210 ptr2 = info->pict.data[2];
212 put_buffer(pb, ptr1, n);
213 put_buffer(pb, ptr2, n);
214 ptr1 += info->pict.linesize[1];
215 ptr2 += info->pict.linesize[2];
218 put_flush_packet(pb);
222 static int pam_read(ByteIOContext *f,
223 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
225 int i, n, linesize, h, w, depth, maxval;
226 char buf1[32], tuple_type[32];
228 AVImageInfo info1, *info = &info1;
231 pnm_get(f, buf1, sizeof(buf1));
232 if (strcmp(buf1, "P7") != 0)
233 return AVERROR_INVALIDDATA;
238 tuple_type[0] = '\0';
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")) {
259 return AVERROR_INVALIDDATA;
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;
269 info->pix_fmt = PIX_FMT_MONOWHITE;
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;
277 return AVERROR_INVALIDDATA;
279 ret = alloc_cb(opaque, info);
283 switch(info->pix_fmt) {
285 return AVERROR_INVALIDDATA;
292 case PIX_FMT_MONOWHITE:
293 n = (info->width + 7) >> 3;
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);
303 ptr = info->pict.data[0];
304 linesize = info->pict.linesize[0];
305 for(i = 0; i < info->height; i++) {
308 for(j = 0;j < w; j++) {
313 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
322 static int pam_write(ByteIOContext *pb, AVImageInfo *info)
324 int i, h, w, n, linesize, depth, maxval;
325 const char *tuple_type;
331 switch(info->pix_fmt) {
332 case PIX_FMT_MONOWHITE:
333 n = (info->width + 7) >> 3;
336 tuple_type = "BLACKANDWHITE";
342 tuple_type = "GRAYSCALE";
354 tuple_type = "RGB_ALPHA";
357 return AVERROR_INVALIDDATA;
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));
364 ptr = info->pict.data[0];
365 linesize = info->pict.linesize[0];
367 if (info->pix_fmt == PIX_FMT_RGBA32) {
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);
383 put_buffer(pb, ptr, n);
387 put_flush_packet(pb);
391 static int pnm_probe(AVProbeData *pd)
393 const char *p = pd->buf;
394 if (pd->buf_size >= 8 &&
396 p[1] >= '4' && p[1] <= '6' &&
398 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
403 static int pgmyuv_probe(AVProbeData *pd)
405 if (match_ext(pd->filename, "pgmyuv"))
406 return AVPROBE_SCORE_MAX;
411 static int pam_probe(AVProbeData *pd)
413 const char *p = pd->buf;
414 if (pd->buf_size >= 8 &&
418 return AVPROBE_SCORE_MAX;
423 AVImageFormat pnm_image_format = {
432 AVImageFormat pbm_image_format = {
437 (1 << PIX_FMT_MONOWHITE),
441 AVImageFormat pgm_image_format = {
446 (1 << PIX_FMT_GRAY8),
450 AVImageFormat ppm_image_format = {
455 (1 << PIX_FMT_RGB24),
459 AVImageFormat pam_image_format = {
464 (1 << PIX_FMT_MONOWHITE) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) |
465 (1 << PIX_FMT_RGBA32),
469 AVImageFormat pgmyuv_image_format = {
474 (1 << PIX_FMT_YUV420P),