annotate pnm.c @ 10612:d6860312274c libavcodec

Support ASCII pnms. Implements issue1452.
author michael
date Tue, 01 Dec 2009 16:56:13 +0000
parents 059265d3cc65
children 914f484bb476
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
1 /*
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
2 * PNM image format
8629
04423b2f6e0b cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents: 7865
diff changeset
3 * Copyright (c) 2002, 2003 Fabrice Bellard
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
4 *
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
5 * This file is part of FFmpeg.
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
6 *
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
11 *
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
15 * Lesser General Public License for more details.
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
16 *
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
20 */
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
21
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
22 #include "avcodec.h"
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
23 #include "pnm.h"
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
24
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
25 static inline int pnm_space(int c)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
26 {
6750
c93570aeb3eb Remove unnecessary parentheses from return calls.
diego
parents: 4985
diff changeset
27 return c == ' ' || c == '\n' || c == '\r' || c == '\t';
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
28 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
29
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
30 static void pnm_get(PNMContext *sc, char *str, int buf_size)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
31 {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
32 char *s;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
33 int c;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
34
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
35 /* skip spaces and comments */
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
36 for (;;) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
37 c = *sc->bytestream++;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
38 if (c == '#') {
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
39 do {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
40 c = *sc->bytestream++;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
41 } while (c != '\n' && sc->bytestream < sc->bytestream_end);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
42 } else if (!pnm_space(c)) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
43 break;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
44 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
45 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
46
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
47 s = str;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
48 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
49 if ((s - str) < buf_size - 1)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
50 *s++ = c;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
51 c = *sc->bytestream++;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
52 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
53 *s = '\0';
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
54 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
55
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
56 int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s)
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
57 {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
58 char buf1[32], tuple_type[32];
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
59 int h, w, depth, maxval;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
60
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
61 pnm_get(s, buf1, sizeof(buf1));
10612
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
62 s->type= buf1[1]-'0';
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
63 if(buf1[0] != 'P')
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
64 return -1;
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
65
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
66 if (s->type==1 || s->type==4) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
67 avctx->pix_fmt = PIX_FMT_MONOWHITE;
10612
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
68 } else if (s->type==2 || s->type==5) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
69 if (avctx->codec_id == CODEC_ID_PGMYUV)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
70 avctx->pix_fmt = PIX_FMT_YUV420P;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
71 else
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
72 avctx->pix_fmt = PIX_FMT_GRAY8;
10612
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
73 } else if (s->type==3 || s->type==6) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
74 avctx->pix_fmt = PIX_FMT_RGB24;
10612
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
75 } else if (s->type==7) {
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
76 w = -1;
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
77 h = -1;
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
78 maxval = -1;
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
79 depth = -1;
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
80 tuple_type[0] = '\0';
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
81 for (;;) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
82 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
83 if (!strcmp(buf1, "WIDTH")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
84 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
85 w = strtol(buf1, NULL, 10);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
86 } else if (!strcmp(buf1, "HEIGHT")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
87 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
88 h = strtol(buf1, NULL, 10);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
89 } else if (!strcmp(buf1, "DEPTH")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
90 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
91 depth = strtol(buf1, NULL, 10);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
92 } else if (!strcmp(buf1, "MAXVAL")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
93 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
94 maxval = strtol(buf1, NULL, 10);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
95 } else if (!strcmp(buf1, "TUPLETYPE")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
96 pnm_get(s, tuple_type, sizeof(tuple_type));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
97 } else if (!strcmp(buf1, "ENDHDR")) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
98 break;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
99 } else {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
100 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
101 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
102 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
103 /* check that all tags are present */
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
104 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h))
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
105 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
106
10459
a6bb56636f90 whitespace cosmetics: K&R coding style, prettyprinting
diego
parents: 9145
diff changeset
107 avctx->width = w;
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
108 avctx->height = h;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
109 if (depth == 1) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
110 if (maxval == 1)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
111 avctx->pix_fmt = PIX_FMT_MONOWHITE;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
112 else
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
113 avctx->pix_fmt = PIX_FMT_GRAY8;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
114 } else if (depth == 3) {
7859
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
115 if (maxval < 256) {
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
116 avctx->pix_fmt = PIX_FMT_RGB24;
7859
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
117 } else {
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
118 av_log(avctx, AV_LOG_ERROR, "16-bit components are only supported for grayscale\n");
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
119 avctx->pix_fmt = PIX_FMT_NONE;
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
120 return -1;
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
121 }
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
122 } else if (depth == 4) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
123 avctx->pix_fmt = PIX_FMT_RGB32;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
124 } else {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
125 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
126 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
127 return 0;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
128 } else {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
129 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
130 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
131 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
132 avctx->width = atoi(buf1);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
133 if (avctx->width <= 0)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
134 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
135 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
136 avctx->height = atoi(buf1);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
137 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
138 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
139 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
140 pnm_get(s, buf1, sizeof(buf1));
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
141 s->maxval = atoi(buf1);
7859
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
142 if (s->maxval >= 256) {
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
143 if (avctx->pix_fmt == PIX_FMT_GRAY8) {
7865
c7420b070961 cosmetics: fix indentation after r15321
jbr
parents: 7859
diff changeset
144 avctx->pix_fmt = PIX_FMT_GRAY16BE;
c7420b070961 cosmetics: fix indentation after r15321
jbr
parents: 7859
diff changeset
145 if (s->maxval != 65535)
c7420b070961 cosmetics: fix indentation after r15321
jbr
parents: 7859
diff changeset
146 avctx->pix_fmt = PIX_FMT_GRAY16;
9145
de31b10455cc pnm: Add missing 'else'. Fixes decoding for 16-bit pgm.
jbr
parents: 9002
diff changeset
147 } else if (avctx->pix_fmt == PIX_FMT_RGB24) {
9002
eb98d61af310 Support 48-bit RGB PPM image.
pross
parents: 8629
diff changeset
148 if (s->maxval > 255)
eb98d61af310 Support 48-bit RGB PPM image.
pross
parents: 8629
diff changeset
149 avctx->pix_fmt = PIX_FMT_RGB48BE;
7859
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
150 } else {
9002
eb98d61af310 Support 48-bit RGB PPM image.
pross
parents: 8629
diff changeset
151 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
7859
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
152 avctx->pix_fmt = PIX_FMT_NONE;
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
153 return -1;
48d00b406a26 Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents: 6750
diff changeset
154 }
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
155 }
10612
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
156 }else
d6860312274c Support ASCII pnms.
michael
parents: 10460
diff changeset
157 s->maxval=1;
4978
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
158 /* more check if YUV420 */
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
159 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
160 if ((avctx->width & 1) != 0)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
161 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
162 h = (avctx->height * 2);
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
163 if ((h % 3) != 0)
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
164 return -1;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
165 h /= 3;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
166 avctx->height = h;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
167 }
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
168 return 0;
95934eef9589 move pnm parser in its own file
aurel
parents:
diff changeset
169 }
10460
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
170
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
171 av_cold int ff_pnm_end(AVCodecContext *avctx)
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
172 {
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
173 PNMContext *s = avctx->priv_data;
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
174
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
175 if (s->picture.data[0])
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
176 avctx->release_buffer(avctx, &s->picture);
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
177
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
178 return 0;
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
179 }
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
180
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
181 av_cold int ff_pnm_init(AVCodecContext *avctx)
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
182 {
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
183 PNMContext *s = avctx->priv_data;
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
184
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
185 avcodec_get_frame_defaults((AVFrame*)&s->picture);
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
186 avctx->coded_frame = (AVFrame*)&s->picture;
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
187
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
188 return 0;
059265d3cc65 Move PNM init/end functions to the PNM common code.
diego
parents: 10459
diff changeset
189 }