FFmpeg
pnm.c
Go to the documentation of this file.
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 
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "libavutil/imgutils.h"
26 #include "avcodec.h"
27 #include "internal.h"
28 #include "pnm.h"
29 
30 static inline int pnm_space(int c)
31 {
32  return c == ' ' || c == '\n' || c == '\r' || c == '\t';
33 }
34 
35 static void pnm_get(PNMContext *sc, char *str, int buf_size)
36 {
37  char *s;
38  int c;
39  uint8_t *bs = sc->bytestream;
40  const uint8_t *end = sc->bytestream_end;
41 
42  /* skip spaces and comments */
43  while (bs < end) {
44  c = *bs++;
45  if (c == '#') {
46  while (c != '\n' && bs < end) {
47  c = *bs++;
48  }
49  } else if (!pnm_space(c)) {
50  break;
51  }
52  }
53 
54  s = str;
55  while (bs < end && !pnm_space(c) && (s - str) < buf_size - 1) {
56  *s++ = c;
57  c = *bs++;
58  }
59  *s = '\0';
60  while (bs < end && !pnm_space(c))
61  c = *bs++;
62  sc->bytestream = bs;
63 }
64 
66 {
67  char buf1[32], tuple_type[32];
68  int h, w, depth, maxval;
69  int ret;
70 
71  pnm_get(s, buf1, sizeof(buf1));
72  if(buf1[0] != 'P')
73  return AVERROR_INVALIDDATA;
74  s->type= buf1[1]-'0';
75 
76  if (s->type==1 || s->type==4) {
78  } else if (s->type==2 || s->type==5) {
79  if (avctx->codec_id == AV_CODEC_ID_PGMYUV)
80  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
81  else
82  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
83  } else if (s->type==3 || s->type==6) {
84  avctx->pix_fmt = AV_PIX_FMT_RGB24;
85  } else if (s->type==7) {
86  w = -1;
87  h = -1;
88  maxval = -1;
89  depth = -1;
90  tuple_type[0] = '\0';
91  for (;;) {
92  pnm_get(s, buf1, sizeof(buf1));
93  if (!strcmp(buf1, "WIDTH")) {
94  pnm_get(s, buf1, sizeof(buf1));
95  w = strtol(buf1, NULL, 10);
96  } else if (!strcmp(buf1, "HEIGHT")) {
97  pnm_get(s, buf1, sizeof(buf1));
98  h = strtol(buf1, NULL, 10);
99  } else if (!strcmp(buf1, "DEPTH")) {
100  pnm_get(s, buf1, sizeof(buf1));
101  depth = strtol(buf1, NULL, 10);
102  } else if (!strcmp(buf1, "MAXVAL")) {
103  pnm_get(s, buf1, sizeof(buf1));
104  maxval = strtol(buf1, NULL, 10);
105  } else if (!strcmp(buf1, "TUPLTYPE") ||
106  /* libavcodec used to write invalid files */
107  !strcmp(buf1, "TUPLETYPE")) {
108  pnm_get(s, tuple_type, sizeof(tuple_type));
109  } else if (!strcmp(buf1, "ENDHDR")) {
110  break;
111  } else {
112  return AVERROR_INVALIDDATA;
113  }
114  }
115  if (!pnm_space(s->bytestream[-1]))
116  return AVERROR_INVALIDDATA;
117 
118  /* check that all tags are present */
119  if (w <= 0 || h <= 0 || maxval <= 0 || maxval > UINT16_MAX || depth <= 0 || tuple_type[0] == '\0' ||
120  av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
121  return AVERROR_INVALIDDATA;
122 
123  ret = ff_set_dimensions(avctx, w, h);
124  if (ret < 0)
125  return ret;
126  s->maxval = maxval;
127  if (depth == 1) {
128  if (maxval == 1) {
129  avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
130  } else if (maxval < 256) {
131  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
132  } else {
133  avctx->pix_fmt = AV_PIX_FMT_GRAY16;
134  }
135  } else if (depth == 2) {
136  if (maxval < 256) {
137  avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
138  } else {
139  avctx->pix_fmt = AV_PIX_FMT_YA16;
140  }
141  } else if (depth == 3) {
142  if (maxval < 256) {
143  avctx->pix_fmt = AV_PIX_FMT_RGB24;
144  } else {
145  avctx->pix_fmt = AV_PIX_FMT_RGB48;
146  }
147  } else if (depth == 4) {
148  if (maxval < 256) {
149  avctx->pix_fmt = AV_PIX_FMT_RGBA;
150  } else {
151  avctx->pix_fmt = AV_PIX_FMT_RGBA64;
152  }
153  } else {
154  return AVERROR_INVALIDDATA;
155  }
156  return 0;
157  } else {
158  return AVERROR_INVALIDDATA;
159  }
160  pnm_get(s, buf1, sizeof(buf1));
161  w = atoi(buf1);
162  pnm_get(s, buf1, sizeof(buf1));
163  h = atoi(buf1);
164  if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
165  return AVERROR_INVALIDDATA;
166 
167  ret = ff_set_dimensions(avctx, w, h);
168  if (ret < 0)
169  return ret;
170 
171  if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
172  pnm_get(s, buf1, sizeof(buf1));
173  s->maxval = atoi(buf1);
174  if (s->maxval <= 0 || s->maxval > UINT16_MAX) {
175  av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
176  s->maxval = 255;
177  }
178  if (s->maxval >= 256) {
179  if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
180  avctx->pix_fmt = AV_PIX_FMT_GRAY16;
181  } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
182  avctx->pix_fmt = AV_PIX_FMT_RGB48;
183  } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) {
184  if (s->maxval < 512)
185  avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
186  else if (s->maxval < 1024)
187  avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
188  else
189  avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
190  } else {
191  av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
192  avctx->pix_fmt = AV_PIX_FMT_NONE;
193  return AVERROR_INVALIDDATA;
194  }
195  }
196  }else
197  s->maxval=1;
198 
199  if (!pnm_space(s->bytestream[-1]))
200  return AVERROR_INVALIDDATA;
201 
202  /* more check if YUV420 */
204  if ((avctx->width & 1) != 0)
205  return AVERROR_INVALIDDATA;
206  h = (avctx->height * 2);
207  if ((h % 3) != 0)
208  return AVERROR_INVALIDDATA;
209  h /= 3;
210  avctx->height = h;
211  }
212  return 0;
213 }
pnm_space
static int pnm_space(int c)
Definition: pnm.c:30
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
w
uint8_t w
Definition: llviddspenc.c:38
internal.h
PNMContext::bytestream_end
uint8_t * bytestream_end
Definition: pnm.h:30
AV_PIX_FMT_MONOWHITE
@ AV_PIX_FMT_MONOWHITE
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:75
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:387
pnm_get
static void pnm_get(PNMContext *sc, char *str, int buf_size)
Definition: pnm.c:35
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:371
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_PIX_FMT_YUV420P9
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:384
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:398
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:1575
AV_PIX_FMT_GRAY8A
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:146
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:377
NULL
#define NULL
Definition: coverity.c:32
AV_PIX_FMT_MONOBLACK
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:76
AV_CODEC_ID_PGMYUV
@ AV_CODEC_ID_PGMYUV
Definition: avcodec.h:283
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
pnm.h
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:373
PNMContext
Definition: pnm.h:27
AV_PIX_FMT_YA16
#define AV_PIX_FMT_YA16
Definition: pixfmt.h:372
uint8_t
uint8_t
Definition: audio_convert.c:194
AVCodecContext::height
int height
Definition: avcodec.h:1738
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1775
avcodec.h
ret
ret
Definition: filter_design.txt:187
PNMContext::bytestream
uint8_t * bytestream
Definition: pnm.h:28
AVCodecContext
main external API structure.
Definition: avcodec.h:1565
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_PIX_FMT_FLAG_PLANAR
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:144
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:104
ff_pnm_decode_header
int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext *const s)
Definition: pnm.c:65
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:1738
imgutils.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
h
h
Definition: vp9dsp_template.c:2038
av_image_check_size
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:282