Mercurial > libavcodec.hg
annotate pnm.c @ 8204:507854688c43 libavcodec
Some BMP files have file size declared in the header equal to headers size
without image data, so try to correct that value before conducting checks on
declared file size.
author | kostya |
---|---|
date | Mon, 24 Nov 2008 11:24:02 +0000 |
parents | c7420b070961 |
children | 04423b2f6e0b |
rev | line source |
---|---|
4978 | 1 /* |
2 * PNM image format | |
3 * Copyright (c) 2002, 2003 Fabrice Bellard. | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
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. | |
11 * | |
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. | |
16 * | |
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 | |
20 */ | |
21 #include "avcodec.h" | |
22 #include "pnm.h" | |
23 | |
24 static inline int pnm_space(int c) | |
25 { | |
6750 | 26 return c == ' ' || c == '\n' || c == '\r' || c == '\t'; |
4978 | 27 } |
28 | |
29 static void pnm_get(PNMContext *sc, char *str, int buf_size) | |
30 { | |
31 char *s; | |
32 int c; | |
33 | |
34 /* skip spaces and comments */ | |
35 for(;;) { | |
36 c = *sc->bytestream++; | |
37 if (c == '#') { | |
38 do { | |
39 c = *sc->bytestream++; | |
40 } while (c != '\n' && sc->bytestream < sc->bytestream_end); | |
41 } else if (!pnm_space(c)) { | |
42 break; | |
43 } | |
44 } | |
45 | |
46 s = str; | |
47 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) { | |
48 if ((s - str) < buf_size - 1) | |
49 *s++ = c; | |
50 c = *sc->bytestream++; | |
51 } | |
52 *s = '\0'; | |
53 } | |
54 | |
55 int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){ | |
56 char buf1[32], tuple_type[32]; | |
57 int h, w, depth, maxval; | |
58 | |
59 pnm_get(s, buf1, sizeof(buf1)); | |
60 if (!strcmp(buf1, "P4")) { | |
61 avctx->pix_fmt = PIX_FMT_MONOWHITE; | |
62 } else if (!strcmp(buf1, "P5")) { | |
63 if (avctx->codec_id == CODEC_ID_PGMYUV) | |
64 avctx->pix_fmt = PIX_FMT_YUV420P; | |
65 else | |
66 avctx->pix_fmt = PIX_FMT_GRAY8; | |
67 } else if (!strcmp(buf1, "P6")) { | |
68 avctx->pix_fmt = PIX_FMT_RGB24; | |
69 } else if (!strcmp(buf1, "P7")) { | |
70 w = -1; | |
71 h = -1; | |
72 maxval = -1; | |
73 depth = -1; | |
74 tuple_type[0] = '\0'; | |
75 for(;;) { | |
76 pnm_get(s, buf1, sizeof(buf1)); | |
77 if (!strcmp(buf1, "WIDTH")) { | |
78 pnm_get(s, buf1, sizeof(buf1)); | |
79 w = strtol(buf1, NULL, 10); | |
80 } else if (!strcmp(buf1, "HEIGHT")) { | |
81 pnm_get(s, buf1, sizeof(buf1)); | |
82 h = strtol(buf1, NULL, 10); | |
83 } else if (!strcmp(buf1, "DEPTH")) { | |
84 pnm_get(s, buf1, sizeof(buf1)); | |
85 depth = strtol(buf1, NULL, 10); | |
86 } else if (!strcmp(buf1, "MAXVAL")) { | |
87 pnm_get(s, buf1, sizeof(buf1)); | |
88 maxval = strtol(buf1, NULL, 10); | |
89 } else if (!strcmp(buf1, "TUPLETYPE")) { | |
90 pnm_get(s, tuple_type, sizeof(tuple_type)); | |
91 } else if (!strcmp(buf1, "ENDHDR")) { | |
92 break; | |
93 } else { | |
94 return -1; | |
95 } | |
96 } | |
97 /* check that all tags are present */ | |
98 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h)) | |
99 return -1; | |
100 | |
101 avctx->width = w; | |
102 avctx->height = h; | |
103 if (depth == 1) { | |
104 if (maxval == 1) | |
105 avctx->pix_fmt = PIX_FMT_MONOWHITE; | |
106 else | |
107 avctx->pix_fmt = PIX_FMT_GRAY8; | |
108 } else if (depth == 3) { | |
7859
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
109 if (maxval < 256) { |
4978 | 110 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
|
111 } else { |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
112 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
|
113 avctx->pix_fmt = PIX_FMT_NONE; |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
114 return -1; |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
115 } |
4978 | 116 } else if (depth == 4) { |
117 avctx->pix_fmt = PIX_FMT_RGB32; | |
118 } else { | |
119 return -1; | |
120 } | |
121 return 0; | |
122 } else { | |
123 return -1; | |
124 } | |
125 pnm_get(s, buf1, sizeof(buf1)); | |
126 avctx->width = atoi(buf1); | |
127 if (avctx->width <= 0) | |
128 return -1; | |
129 pnm_get(s, buf1, sizeof(buf1)); | |
130 avctx->height = atoi(buf1); | |
131 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height)) | |
132 return -1; | |
133 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) { | |
134 pnm_get(s, buf1, sizeof(buf1)); | |
135 s->maxval = atoi(buf1); | |
7859
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
136 if (s->maxval >= 256) { |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
137 if (avctx->pix_fmt == PIX_FMT_GRAY8) { |
7865 | 138 avctx->pix_fmt = PIX_FMT_GRAY16BE; |
139 if (s->maxval != 65535) | |
140 avctx->pix_fmt = PIX_FMT_GRAY16; | |
7859
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
141 } else { |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
142 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
|
143 avctx->pix_fmt = PIX_FMT_NONE; |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
144 return -1; |
48d00b406a26
Return error when trying to decode non-grayscale 16-bit PNM images.
jbr
parents:
6750
diff
changeset
|
145 } |
4978 | 146 } |
147 } | |
148 /* more check if YUV420 */ | |
149 if (avctx->pix_fmt == PIX_FMT_YUV420P) { | |
150 if ((avctx->width & 1) != 0) | |
151 return -1; | |
152 h = (avctx->height * 2); | |
153 if ((h % 3) != 0) | |
154 return -1; | |
155 h /= 3; | |
156 avctx->height = h; | |
157 } | |
158 return 0; | |
159 } |