3 * Copyright (c) 2002, 2003 Fabrice Bellard
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/imgutils.h"
29 static inline int pnm_space(int c
)
31 return c
== ' ' || c
== '\n' || c
== '\r' || c
== '\t';
34 static void pnm_get(PNMContext
*sc
, char *str
, int buf_size
)
39 /* skip spaces and comments */
41 c
= *sc
->bytestream
++;
44 c
= *sc
->bytestream
++;
45 } while (c
!= '\n' && sc
->bytestream
< sc
->bytestream_end
);
46 } else if (!pnm_space(c
)) {
52 while (sc
->bytestream
< sc
->bytestream_end
&& !pnm_space(c
)) {
53 if ((s
- str
) < buf_size
- 1)
55 c
= *sc
->bytestream
++;
60 int ff_pnm_decode_header(AVCodecContext
*avctx
, PNMContext
* const s
)
62 char buf1
[32], tuple_type
[32];
63 int h
, w
, depth
, maxval
;
65 pnm_get(s
, buf1
, sizeof(buf1
));
68 return AVERROR_INVALIDDATA
;
70 if (s
->type
==1 || s
->type
==4) {
71 avctx
->pix_fmt
= AV_PIX_FMT_MONOWHITE
;
72 } else if (s
->type
==2 || s
->type
==5) {
73 if (avctx
->codec_id
== AV_CODEC_ID_PGMYUV
)
74 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
76 avctx
->pix_fmt
= AV_PIX_FMT_GRAY8
;
77 } else if (s
->type
==3 || s
->type
==6) {
78 avctx
->pix_fmt
= AV_PIX_FMT_RGB24
;
79 } else if (s
->type
==7) {
86 pnm_get(s
, buf1
, sizeof(buf1
));
87 if (!strcmp(buf1
, "WIDTH")) {
88 pnm_get(s
, buf1
, sizeof(buf1
));
89 w
= strtol(buf1
, NULL
, 10);
90 } else if (!strcmp(buf1
, "HEIGHT")) {
91 pnm_get(s
, buf1
, sizeof(buf1
));
92 h
= strtol(buf1
, NULL
, 10);
93 } else if (!strcmp(buf1
, "DEPTH")) {
94 pnm_get(s
, buf1
, sizeof(buf1
));
95 depth
= strtol(buf1
, NULL
, 10);
96 } else if (!strcmp(buf1
, "MAXVAL")) {
97 pnm_get(s
, buf1
, sizeof(buf1
));
98 maxval
= strtol(buf1
, NULL
, 10);
99 } else if (!strcmp(buf1
, "TUPLTYPE") ||
100 /* libavcodec used to write invalid files */
101 !strcmp(buf1
, "TUPLETYPE")) {
102 pnm_get(s
, tuple_type
, sizeof(tuple_type
));
103 } else if (!strcmp(buf1
, "ENDHDR")) {
106 return AVERROR_INVALIDDATA
;
109 /* check that all tags are present */
110 if (w
<= 0 || h
<= 0 || maxval
<= 0 || depth
<= 0 || tuple_type
[0] == '\0' || av_image_check_size(w
, h
, 0, avctx
))
111 return AVERROR_INVALIDDATA
;
117 avctx
->pix_fmt
= AV_PIX_FMT_MONOWHITE
;
119 avctx
->pix_fmt
= AV_PIX_FMT_GRAY8
;
120 } else if (depth
== 3) {
122 avctx
->pix_fmt
= AV_PIX_FMT_RGB24
;
124 av_log(avctx
, AV_LOG_ERROR
, "16-bit components are only supported for grayscale\n");
125 avctx
->pix_fmt
= AV_PIX_FMT_NONE
;
126 return AVERROR_INVALIDDATA
;
128 } else if (depth
== 4) {
129 avctx
->pix_fmt
= AV_PIX_FMT_RGB32
;
131 return AVERROR_INVALIDDATA
;
135 return AVERROR_INVALIDDATA
;
137 pnm_get(s
, buf1
, sizeof(buf1
));
138 avctx
->width
= atoi(buf1
);
139 if (avctx
->width
<= 0)
140 return AVERROR_INVALIDDATA
;
141 pnm_get(s
, buf1
, sizeof(buf1
));
142 avctx
->height
= atoi(buf1
);
143 if(av_image_check_size(avctx
->width
, avctx
->height
, 0, avctx
))
144 return AVERROR_INVALIDDATA
;
145 if (avctx
->pix_fmt
!= AV_PIX_FMT_MONOWHITE
) {
146 pnm_get(s
, buf1
, sizeof(buf1
));
147 s
->maxval
= atoi(buf1
);
148 if (s
->maxval
<= 0) {
149 av_log(avctx
, AV_LOG_ERROR
, "Invalid maxval: %d\n", s
->maxval
);
152 if (s
->maxval
>= 256) {
153 if (avctx
->pix_fmt
== AV_PIX_FMT_GRAY8
) {
154 avctx
->pix_fmt
= AV_PIX_FMT_GRAY16BE
;
155 if (s
->maxval
!= 65535)
156 avctx
->pix_fmt
= AV_PIX_FMT_GRAY16
;
157 } else if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
) {
159 avctx
->pix_fmt
= AV_PIX_FMT_RGB48BE
;
160 } else if (avctx
->pix_fmt
== AV_PIX_FMT_YUV420P
&& s
->maxval
< 65536) {
162 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P9BE
;
163 else if (s
->maxval
< 1024)
164 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P10BE
;
166 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P16
;
168 av_log(avctx
, AV_LOG_ERROR
, "Unsupported pixel format\n");
169 avctx
->pix_fmt
= AV_PIX_FMT_NONE
;
170 return AVERROR_INVALIDDATA
;
175 /* more check if YUV420 */
176 if (av_pix_fmt_desc_get(avctx
->pix_fmt
)->flags
& AV_PIX_FMT_FLAG_PLANAR
) {
177 if ((avctx
->width
& 1) != 0)
178 return AVERROR_INVALIDDATA
;
179 h
= (avctx
->height
* 2);
181 return AVERROR_INVALIDDATA
;