FFmpeg  4.2.2
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 }
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
static int pnm_space(int c)
Definition: pnm.c:30
misc image utilities
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
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
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:377
int maxval
maximum value of a pixel
Definition: pnm.h:31
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1775
uint8_t * bytestream
Definition: pnm.h:28
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AV_PIX_FMT_YA16
Definition: pixfmt.h:372
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:373
static void pnm_get(PNMContext *sc, char *str, int buf_size)
Definition: pnm.c:35
uint8_t * bytestream_end
Definition: pnm.h:30
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
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
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:146
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:371
int width
picture width / height.
Definition: avcodec.h:1738
uint8_t w
Definition: llviddspenc.c:38
#define s(width, name)
Definition: cbs_vp9.c:257
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:398
Definition: pnm.h:27
Libavcodec external API header.
enum AVCodecID codec_id
Definition: avcodec.h:1575
int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext *const s)
Definition: pnm.c:65
main external API structure.
Definition: avcodec.h:1565
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:387
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:384
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb...
Definition: pixfmt.h:76
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
common internal api header.
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb...
Definition: pixfmt.h:75
static double c[64]
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:144
int type
Definition: pnm.h:32