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
),