FFmpeg  4.4.5
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/avassert.h"
26 #include "libavutil/imgutils.h"
27 #include "libavutil/avstring.h"
28 #include "avcodec.h"
29 #include "internal.h"
30 #include "pnm.h"
31 
32 static inline int pnm_space(int c)
33 {
34  return c == ' ' || c == '\n' || c == '\r' || c == '\t';
35 }
36 
37 static void pnm_get(PNMContext *sc, char *str, int buf_size)
38 {
39  char *s;
40  int c;
41  uint8_t *bs = sc->bytestream;
42  const uint8_t *end = sc->bytestream_end;
43 
44  /* skip spaces and comments */
45  while (bs < end) {
46  c = *bs++;
47  if (c == '#') {
48  while (c != '\n' && bs < end) {
49  c = *bs++;
50  }
51  } else if (!pnm_space(c)) {
52  break;
53  }
54  }
55 
56  s = str;
57  while (bs < end && !pnm_space(c) && (s - str) < buf_size - 1) {
58  *s++ = c;
59  c = *bs++;
60  }
61  *s = '\0';
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  if (s->bytestream_end - s->bytestream < 3 ||
72  s->bytestream[0] != 'P' ||
73  (s->bytestream[1] < '1' ||
74  s->bytestream[1] > '7' &&
75  s->bytestream[1] != 'f' &&
76  s->bytestream[1] != 'F')) {
77  s->bytestream += s->bytestream_end > s->bytestream;
78  s->bytestream += s->bytestream_end > s->bytestream;
79  return AVERROR_INVALIDDATA;
80  }
81  pnm_get(s, buf1, sizeof(buf1));
82  s->type= buf1[1]-'0';
83 
84  if (buf1[1] == 'F') {
85  avctx->pix_fmt = AV_PIX_FMT_GBRPF32;
86  } else if (buf1[1] == 'f') {
87  avctx->pix_fmt = AV_PIX_FMT_GRAYF32;
88  } else if (s->type==1 || s->type==4) {
90  } else if (s->type==2 || s->type==5) {
91  if (avctx->codec_id == AV_CODEC_ID_PGMYUV)
92  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
93  else
94  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
95  } else if (s->type==3 || s->type==6) {
96  avctx->pix_fmt = AV_PIX_FMT_RGB24;
97  } else if (s->type==7) {
98  w = -1;
99  h = -1;
100  maxval = -1;
101  depth = -1;
102  tuple_type[0] = '\0';
103  for (;;) {
104  pnm_get(s, buf1, sizeof(buf1));
105  if (!strcmp(buf1, "WIDTH")) {
106  pnm_get(s, buf1, sizeof(buf1));
107  w = strtol(buf1, NULL, 10);
108  } else if (!strcmp(buf1, "HEIGHT")) {
109  pnm_get(s, buf1, sizeof(buf1));
110  h = strtol(buf1, NULL, 10);
111  } else if (!strcmp(buf1, "DEPTH")) {
112  pnm_get(s, buf1, sizeof(buf1));
113  depth = strtol(buf1, NULL, 10);
114  } else if (!strcmp(buf1, "MAXVAL")) {
115  pnm_get(s, buf1, sizeof(buf1));
116  maxval = strtol(buf1, NULL, 10);
117  } else if (!strcmp(buf1, "TUPLTYPE") ||
118  /* libavcodec used to write invalid files */
119  !strcmp(buf1, "TUPLETYPE")) {
120  pnm_get(s, tuple_type, sizeof(tuple_type));
121  } else if (!strcmp(buf1, "ENDHDR")) {
122  break;
123  } else {
124  return AVERROR_INVALIDDATA;
125  }
126  }
127  if (!pnm_space(s->bytestream[-1]))
128  return AVERROR_INVALIDDATA;
129 
130  /* check that all tags are present */
131  if (w <= 0 || h <= 0 || maxval <= 0 || maxval > UINT16_MAX || depth <= 0 || tuple_type[0] == '\0' ||
132  av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
133  return AVERROR_INVALIDDATA;
134 
135  ret = ff_set_dimensions(avctx, w, h);
136  if (ret < 0)
137  return ret;
138  s->maxval = maxval;
139  if (depth == 1) {
140  if (maxval == 1) {
141  avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
142  } else if (maxval < 256) {
143  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
144  } else {
145  avctx->pix_fmt = AV_PIX_FMT_GRAY16;
146  }
147  } else if (depth == 2) {
148  if (maxval < 256) {
149  avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
150  } else {
151  avctx->pix_fmt = AV_PIX_FMT_YA16;
152  }
153  } else if (depth == 3) {
154  if (maxval < 256) {
155  avctx->pix_fmt = AV_PIX_FMT_RGB24;
156  } else {
157  avctx->pix_fmt = AV_PIX_FMT_RGB48;
158  }
159  } else if (depth == 4) {
160  if (maxval < 256) {
161  avctx->pix_fmt = AV_PIX_FMT_RGBA;
162  } else {
163  avctx->pix_fmt = AV_PIX_FMT_RGBA64;
164  }
165  } else {
166  return AVERROR_INVALIDDATA;
167  }
168  return 0;
169  } else {
170  av_assert0(0);
171  }
172  pnm_get(s, buf1, sizeof(buf1));
173  w = atoi(buf1);
174  pnm_get(s, buf1, sizeof(buf1));
175  h = atoi(buf1);
176  if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
177  return AVERROR_INVALIDDATA;
178 
179  ret = ff_set_dimensions(avctx, w, h);
180  if (ret < 0)
181  return ret;
182 
183  if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32 || avctx->pix_fmt == AV_PIX_FMT_GRAYF32) {
184  pnm_get(s, buf1, sizeof(buf1));
185  if (av_sscanf(buf1, "%f", &s->scale) != 1 || s->scale == 0.0 || !isfinite(s->scale)) {
186  av_log(avctx, AV_LOG_ERROR, "Invalid scale.\n");
187  return AVERROR_INVALIDDATA;
188  }
189  s->endian = s->scale < 0.f;
190  s->scale = fabsf(s->scale);
191  s->maxval = (1ULL << 32) - 1;
192  } else if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
193  pnm_get(s, buf1, sizeof(buf1));
194  s->maxval = atoi(buf1);
195  if (s->maxval <= 0 || s->maxval > UINT16_MAX) {
196  av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
197  s->maxval = 255;
198  }
199  if (s->maxval >= 256) {
200  if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
201  avctx->pix_fmt = AV_PIX_FMT_GRAY16;
202  } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
203  avctx->pix_fmt = AV_PIX_FMT_RGB48;
204  } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) {
205  if (s->maxval < 512)
206  avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
207  else if (s->maxval < 1024)
208  avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
209  else
210  avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
211  } else {
212  av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
213  avctx->pix_fmt = AV_PIX_FMT_NONE;
214  return AVERROR_INVALIDDATA;
215  }
216  }
217  }else
218  s->maxval=1;
219 
220  if (!pnm_space(s->bytestream[-1]))
221  return AVERROR_INVALIDDATA;
222 
223  /* more check if YUV420 */
225  avctx->pix_fmt != AV_PIX_FMT_GBRPF32) {
226  if ((avctx->width & 1) != 0)
227  return AVERROR_INVALIDDATA;
228  h = (avctx->height * 2);
229  if ((h % 3) != 0)
230  return AVERROR_INVALIDDATA;
231  h /= 3;
232  avctx->height = h;
233  }
234  return 0;
235 }
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Libavcodec external API header.
#define s(width, name)
Definition: cbs_vp9.c:257
#define NULL
Definition: coverity.c:32
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
@ AV_CODEC_ID_PGMYUV
Definition: codec_id.h:114
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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:317
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:962
misc image utilities
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:84
common internal API header
#define isfinite(x)
Definition: libm.h:359
uint8_t w
Definition: llviddspenc.c:39
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:144
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:410
#define AV_PIX_FMT_GBRPF32
Definition: pixfmt.h:428
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:399
#define AV_PIX_FMT_YA16
Definition: pixfmt.h:384
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:389
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:396
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:385
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:431
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
@ 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_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_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:146
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
@ 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
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
static int pnm_space(int c)
Definition: pnm.c:32
static void pnm_get(PNMContext *sc, char *str, int buf_size)
Definition: pnm.c:37
int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext *const s)
Definition: pnm.c:65
main external API structure.
Definition: avcodec.h:536
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:746
int width
picture width / height.
Definition: avcodec.h:709
enum AVCodecID codec_id
Definition: avcodec.h:546
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
Definition: pnm.h:27
uint8_t * bytestream_end
Definition: pnm.h:30
uint8_t * bytestream
Definition: pnm.h:28
#define av_log(a,...)
static double c[64]