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 typedef struct PNMContext {
23 uint8_t *bytestream_start;
24 uint8_t *bytestream_end;
28 static inline int pnm_space(int c)
30 return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
33 static void pnm_get(PNMContext *sc, char *str, int buf_size)
38 /* skip spaces and comments */
40 c = *sc->bytestream++;
43 c = *sc->bytestream++;
44 } while (c != '\n' && sc->bytestream < sc->bytestream_end);
45 } else if (!pnm_space(c)) {
51 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
52 if ((s - str) < buf_size - 1)
54 c = *sc->bytestream++;
59 static int common_init(AVCodecContext *avctx){
60 PNMContext *s = avctx->priv_data;
62 avcodec_get_frame_defaults((AVFrame*)&s->picture);
63 avctx->coded_frame= (AVFrame*)&s->picture;
68 static int pnm_decode_frame(AVCodecContext *avctx,
69 void *data, int *data_size,
70 uint8_t *buf, int buf_size)
72 PNMContext * const s = avctx->priv_data;
73 AVFrame *picture = data;
74 AVFrame * const p= (AVFrame*)&s->picture;
75 int i, n, linesize, h;
79 /* special case for last picture */
86 s->bytestream_end= buf + buf_size;
88 pnm_get(s, buf1, sizeof(buf1));
89 if (!strcmp(buf1, "P4")) {
90 avctx->pix_fmt = PIX_FMT_MONOWHITE;
91 } else if (!strcmp(buf1, "P5")) {
92 if (avctx->codec_id == CODEC_ID_PGMYUV)
93 avctx->pix_fmt = PIX_FMT_YUV420P;
95 avctx->pix_fmt = PIX_FMT_GRAY8;
96 } else if (!strcmp(buf1, "P6")) {
97 avctx->pix_fmt = PIX_FMT_RGB24;
101 pnm_get(s, buf1, sizeof(buf1));
102 avctx->width = atoi(buf1);
103 if (avctx->width <= 0)
105 pnm_get(s, buf1, sizeof(buf1));
106 avctx->height = atoi(buf1);
107 if (avctx->height <= 0)
109 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
110 pnm_get(s, buf1, sizeof(buf1));
113 /* more check if YUV420 */
114 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
115 if ((avctx->width & 1) != 0)
117 h = (avctx->height * 2);
125 avctx->release_buffer(avctx, p);
128 if(avctx->get_buffer(avctx, p) < 0){
129 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
132 p->pict_type= FF_I_TYPE;
135 switch(avctx->pix_fmt) {
139 n = avctx->width * 3;
144 case PIX_FMT_MONOWHITE:
145 n = (avctx->width + 7) >> 3;
148 linesize = p->linesize[0];
149 for(i = 0; i < avctx->height; i++) {
150 memcpy(ptr, s->bytestream, n);
155 case PIX_FMT_YUV420P:
157 unsigned char *ptr1, *ptr2;
161 linesize = p->linesize[0];
162 for(i = 0; i < avctx->height; i++) {
163 memcpy(ptr, s->bytestream, n);
170 h = avctx->height >> 1;
171 for(i = 0; i < h; i++) {
172 memcpy(ptr1, s->bytestream, n);
174 memcpy(ptr2, s->bytestream, n);
176 ptr1 += p->linesize[1];
177 ptr2 += p->linesize[2];
182 *picture= *(AVFrame*)&s->picture;
183 *data_size = sizeof(AVPicture);
185 return s->bytestream - s->bytestream_start;
188 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
189 PNMContext *s = avctx->priv_data;
190 AVFrame *pict = data;
191 AVFrame * const p= (AVFrame*)&s->picture;
192 int i, h, h1, c, n, linesize;
193 uint8_t *ptr, *ptr1, *ptr2;
196 p->pict_type= FF_I_TYPE;
200 s->bytestream= outbuf;
201 s->bytestream_end= outbuf+buf_size;
205 switch(avctx->pix_fmt) {
206 case PIX_FMT_MONOWHITE:
208 n = (avctx->width + 7) >> 3;
216 n = avctx->width * 3;
218 case PIX_FMT_YUV420P:
226 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
228 c, avctx->width, h1);
229 s->bytestream += strlen(s->bytestream);
230 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
231 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
233 s->bytestream += strlen(s->bytestream);
237 linesize = p->linesize[0];
239 memcpy(s->bytestream, ptr, n);
244 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
250 memcpy(s->bytestream, ptr1, n);
252 memcpy(s->bytestream, ptr2, n);
254 ptr1 += p->linesize[1];
255 ptr2 += p->linesize[2];
258 return s->bytestream - s->bytestream_start;
261 static int pam_decode_frame(AVCodecContext *avctx,
262 void *data, int *data_size,
263 uint8_t *buf, int buf_size)
265 PNMContext * const s = avctx->priv_data;
266 AVFrame *picture = data;
267 AVFrame * const p= (AVFrame*)&s->picture;
268 int i, n, linesize, h, w, depth, maxval;
269 char buf1[32], tuple_type[32];
272 /* special case for last picture */
279 s->bytestream_end= buf + buf_size;
281 pnm_get(s, buf1, sizeof(buf1));
282 if (strcmp(buf1, "P7") != 0)
288 tuple_type[0] = '\0';
290 pnm_get(s, buf1, sizeof(buf1));
291 if (!strcmp(buf1, "WIDTH")) {
292 pnm_get(s, buf1, sizeof(buf1));
293 w = strtol(buf1, NULL, 10);
294 } else if (!strcmp(buf1, "HEIGHT")) {
295 pnm_get(s, buf1, sizeof(buf1));
296 h = strtol(buf1, NULL, 10);
297 } else if (!strcmp(buf1, "DEPTH")) {
298 pnm_get(s, buf1, sizeof(buf1));
299 depth = strtol(buf1, NULL, 10);
300 } else if (!strcmp(buf1, "MAXVAL")) {
301 pnm_get(s, buf1, sizeof(buf1));
302 maxval = strtol(buf1, NULL, 10);
303 } else if (!strcmp(buf1, "TUPLETYPE")) {
304 pnm_get(s, tuple_type, sizeof(tuple_type));
305 } else if (!strcmp(buf1, "ENDHDR")) {
311 /* check that all tags are present */
312 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0')
318 avctx->pix_fmt = PIX_FMT_MONOWHITE;
320 avctx->pix_fmt = PIX_FMT_GRAY8;
321 } else if (depth == 3) {
322 avctx->pix_fmt = PIX_FMT_RGB24;
323 } else if (depth == 4) {
324 avctx->pix_fmt = PIX_FMT_RGBA32;
330 avctx->release_buffer(avctx, p);
333 if(avctx->get_buffer(avctx, p) < 0){
334 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
337 p->pict_type= FF_I_TYPE;
340 switch(avctx->pix_fmt) {
344 n = avctx->width * 3;
349 case PIX_FMT_MONOWHITE:
350 n = (avctx->width + 7) >> 3;
353 linesize = p->linesize[0];
354 for(i = 0; i < avctx->height; i++) {
355 memcpy(ptr, s->bytestream, n);
362 linesize = p->linesize[0];
363 for(i = 0; i < avctx->height; i++) {
366 for(j = 0;j < w; j++) {
367 r = *s->bytestream++;
368 g = *s->bytestream++;
369 b = *s->bytestream++;
370 a = *s->bytestream++;
371 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
377 *picture= *(AVFrame*)&s->picture;
378 *data_size = sizeof(AVPicture);
380 return s->bytestream - s->bytestream_start;
383 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
384 PNMContext *s = avctx->priv_data;
385 AVFrame *pict = data;
386 AVFrame * const p= (AVFrame*)&s->picture;
387 int i, h, w, n, linesize, depth, maxval;
388 const char *tuple_type;
392 p->pict_type= FF_I_TYPE;
396 s->bytestream= outbuf;
397 s->bytestream_end= outbuf+buf_size;
401 switch(avctx->pix_fmt) {
402 case PIX_FMT_MONOWHITE:
406 tuple_type = "BLACKANDWHITE";
412 tuple_type = "GRAYSCALE";
424 tuple_type = "RGB_ALPHA";
429 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
430 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
431 w, h, depth, maxval, tuple_type);
432 s->bytestream += strlen(s->bytestream);
435 linesize = p->linesize[0];
437 if (avctx->pix_fmt == PIX_FMT_RGBA32) {
443 v = ((uint32_t *)ptr)[j];
444 *s->bytestream++ = v >> 16;
445 *s->bytestream++ = v >> 8;
446 *s->bytestream++ = v;
447 *s->bytestream++ = v >> 24;
453 memcpy(s->bytestream, ptr, n);
458 return s->bytestream - s->bytestream_start;
462 static int pnm_probe(AVProbeData *pd)
464 const char *p = pd->buf;
465 if (pd->buf_size >= 8 &&
467 p[1] >= '4' && p[1] <= '6' &&
469 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
474 static int pgmyuv_probe(AVProbeData *pd)
476 if (match_ext(pd->filename, "pgmyuv"))
477 return AVPROBE_SCORE_MAX;
482 static int pam_probe(AVProbeData *pd)
484 const char *p = pd->buf;
485 if (pd->buf_size >= 8 &&
489 return AVPROBE_SCORE_MAX;
495 AVCodec pgm_encoder = {
504 .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, -1},
507 AVCodec pgmyuv_encoder = {
516 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
519 AVCodec ppm_encoder = {
528 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, -1},
531 AVCodec pbm_encoder = {
540 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, -1},
543 AVCodec pam_encoder = {
552 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, -1},