Coverage Report

Created: 2023-06-07 06:03

/src/libjpeg-turbo.2.0.x/rdppm.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * rdppm.c
3
 *
4
 * This file was part of the Independent JPEG Group's software:
5
 * Copyright (C) 1991-1997, Thomas G. Lane.
6
 * Modified 2009 by Bill Allombert, Guido Vollbeding.
7
 * libjpeg-turbo Modifications:
8
 * Copyright (C) 2015-2017, 2020-2023, D. R. Commander.
9
 * For conditions of distribution and use, see the accompanying README.ijg
10
 * file.
11
 *
12
 * This file contains routines to read input images in PPM/PGM format.
13
 * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
14
 * The PBMPLUS library is NOT required to compile this software
15
 * (but it is highly useful as a set of PPM image manipulation programs).
16
 *
17
 * These routines may need modification for non-Unix environments or
18
 * specialized applications.  As they stand, they assume input from
19
 * an ordinary stdio stream.  They further assume that reading begins
20
 * at the start of the file; start_input may need work if the
21
 * user interface has already read some data (e.g., to determine that
22
 * the file is indeed PPM format).
23
 */
24
25
#include "cmyk.h"
26
#include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
27
28
#ifdef PPM_SUPPORTED
29
30
31
/* Portions of this code are based on the PBMPLUS library, which is:
32
**
33
** Copyright (C) 1988 by Jef Poskanzer.
34
**
35
** Permission to use, copy, modify, and distribute this software and its
36
** documentation for any purpose and without fee is hereby granted, provided
37
** that the above copyright notice appear in all copies and that both that
38
** copyright notice and this permission notice appear in supporting
39
** documentation.  This software is provided "as is" without express or
40
** implied warranty.
41
*/
42
43
44
/* Macros to deal with unsigned chars as efficiently as compiler allows */
45
46
#ifdef HAVE_UNSIGNED_CHAR
47
typedef unsigned char U_CHAR;
48
169M
#define UCH(x)  ((int)(x))
49
#else /* !HAVE_UNSIGNED_CHAR */
50
#ifdef __CHAR_UNSIGNED__
51
typedef char U_CHAR;
52
#define UCH(x)  ((int)(x))
53
#else
54
typedef char U_CHAR;
55
#define UCH(x)  ((int)(x) & 0xFF)
56
#endif
57
#endif /* HAVE_UNSIGNED_CHAR */
58
59
60
#define ReadOK(file, buffer, len) \
61
313M
  (JFREAD(file, buffer, len) == ((size_t)(len)))
62
63
static int alpha_index[JPEG_NUMCS] = {
64
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1
65
};
66
67
68
/* Private version of data source object */
69
70
typedef struct {
71
  struct cjpeg_source_struct pub; /* public fields */
72
73
  /* Usually these two pointers point to the same place: */
74
  U_CHAR *iobuffer;             /* fread's I/O buffer */
75
  JSAMPROW pixrow;              /* compressor input buffer */
76
  size_t buffer_width;          /* width of I/O buffer */
77
  JSAMPLE *rescale;             /* => maxval-remapping array, or NULL */
78
  unsigned int maxval;
79
} ppm_source_struct;
80
81
typedef ppm_source_struct *ppm_source_ptr;
82
83
84
LOCAL(int)
85
pbm_getc(FILE *infile)
86
/* Read next char, skipping over any comments */
87
/* A comment/newline sequence is returned as a newline */
88
3.07M
{
89
3.07M
  register int ch;
90
91
3.07M
  ch = getc(infile);
92
3.07M
  if (ch == '#') {
93
582k
    do {
94
582k
      ch = getc(infile);
95
582k
    } while (ch != '\n' && ch != EOF);
96
56.1k
  }
97
3.07M
  return ch;
98
3.07M
}
99
100
101
LOCAL(unsigned int)
102
read_pbm_integer(j_compress_ptr cinfo, FILE *infile, unsigned int maxval)
103
/* Read an unsigned decimal integer from the PPM file */
104
/* Swallows one trailing character after the integer */
105
/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
106
/* This should not be a problem in practice. */
107
1.25M
{
108
1.25M
  register int ch;
109
1.25M
  register unsigned int val;
110
111
  /* Skip any leading whitespace */
112
1.36M
  do {
113
1.36M
    ch = pbm_getc(infile);
114
1.36M
    if (ch == EOF)
115
25.4k
      ERREXIT(cinfo, JERR_INPUT_EOF);
116
1.36M
  } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
117
118
1.25M
  if (ch < '0' || ch > '9')
119
2.56k
    ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
120
121
1.25M
  val = ch - '0';
122
1.73M
  while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
123
477k
    val *= 10;
124
477k
    val += ch - '0';
125
477k
    if (val > maxval)
126
1.58k
      ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
127
477k
  }
128
129
1.25M
  return val;
130
1.25M
}
131
132
133
/*
134
 * Read one row of pixels.
135
 *
136
 * We provide several different versions depending on input file format.
137
 * In all cases, input is scaled to the size of JSAMPLE.
138
 *
139
 * A really fast path is provided for reading byte/sample raw files with
140
 * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
141
 */
142
143
144
METHODDEF(JDIMENSION)
145
get_text_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
146
/* This version is for reading text-format PGM files with any maxval */
147
22.7k
{
148
22.7k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
149
22.7k
  FILE *infile = source->pub.input_file;
150
22.7k
  register JSAMPROW ptr;
151
22.7k
  register JSAMPLE *rescale = source->rescale;
152
22.7k
  JDIMENSION col;
153
22.7k
  unsigned int maxval = source->maxval;
154
155
22.7k
  ptr = source->pub.buffer[0];
156
61.7k
  for (col = cinfo->image_width; col > 0; col--) {
157
39.0k
    *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)];
158
39.0k
  }
159
22.7k
  return 1;
160
22.7k
}
161
162
163
232M
#define GRAY_RGB_READ_LOOP(read_op, alpha_set_op) { \
164
747M
  for (col = cinfo->image_width; col > 0; col--) { \
165
514M
    ptr[rindex] = ptr[gindex] = ptr[bindex] = read_op; \
166
514M
    alpha_set_op \
167
514M
    ptr += ps; \
168
514M
  } \
169
232M
}
170
171
METHODDEF(JDIMENSION)
172
get_text_gray_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
173
/* This version is for reading text-format PGM files with any maxval and
174
   converting to extended RGB */
175
110k
{
176
110k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
177
110k
  FILE *infile = source->pub.input_file;
178
110k
  register JSAMPROW ptr;
179
110k
  register JSAMPLE *rescale = source->rescale;
180
110k
  JDIMENSION col;
181
110k
  unsigned int maxval = source->maxval;
182
110k
  register int rindex = rgb_red[cinfo->in_color_space];
183
110k
  register int gindex = rgb_green[cinfo->in_color_space];
184
110k
  register int bindex = rgb_blue[cinfo->in_color_space];
185
110k
  register int aindex = alpha_index[cinfo->in_color_space];
186
110k
  register int ps = rgb_pixelsize[cinfo->in_color_space];
187
188
110k
  ptr = source->pub.buffer[0];
189
110k
  if (maxval == MAXJSAMPLE) {
190
18.9k
    if (aindex >= 0)
191
2.18k
      GRAY_RGB_READ_LOOP((JSAMPLE)read_pbm_integer(cinfo, infile, maxval),
192
18.9k
                         ptr[aindex] = MAXJSAMPLE;)
193
16.8k
    else
194
16.8k
      GRAY_RGB_READ_LOOP((JSAMPLE)read_pbm_integer(cinfo, infile, maxval), {})
195
91.1k
  } else {
196
91.1k
    if (aindex >= 0)
197
13.9k
      GRAY_RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)],
198
91.1k
                         ptr[aindex] = MAXJSAMPLE;)
199
77.1k
    else
200
77.1k
      GRAY_RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], {})
201
91.1k
  }
202
110k
  return 1;
203
110k
}
204
205
206
METHODDEF(JDIMENSION)
207
get_text_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
208
/* This version is for reading text-format PGM files with any maxval and
209
   converting to CMYK */
210
16.1k
{
211
16.1k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
212
16.1k
  FILE *infile = source->pub.input_file;
213
16.1k
  register JSAMPROW ptr;
214
16.1k
  register JSAMPLE *rescale = source->rescale;
215
16.1k
  JDIMENSION col;
216
16.1k
  unsigned int maxval = source->maxval;
217
218
16.1k
  ptr = source->pub.buffer[0];
219
16.1k
  if (maxval == MAXJSAMPLE) {
220
7.62k
    for (col = cinfo->image_width; col > 0; col--) {
221
5.44k
      JSAMPLE gray = (JSAMPLE)read_pbm_integer(cinfo, infile, maxval);
222
5.44k
      rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
223
5.44k
      ptr += 4;
224
5.44k
    }
225
13.9k
  } else {
226
34.3k
    for (col = cinfo->image_width; col > 0; col--) {
227
20.3k
      JSAMPLE gray = rescale[read_pbm_integer(cinfo, infile, maxval)];
228
20.3k
      rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
229
20.3k
      ptr += 4;
230
20.3k
    }
231
13.9k
  }
232
16.1k
  return 1;
233
16.1k
}
234
235
236
3.01M
#define RGB_READ_LOOP(read_op, alpha_set_op) { \
237
29.3M
  for (col = cinfo->image_width; col > 0; col--) { \
238
26.3M
    ptr[rindex] = read_op; \
239
26.3M
    ptr[gindex] = read_op; \
240
26.3M
    ptr[bindex] = read_op; \
241
26.3M
    alpha_set_op \
242
26.3M
    ptr += ps; \
243
26.3M
  } \
244
3.01M
}
245
246
METHODDEF(JDIMENSION)
247
get_text_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
248
/* This version is for reading text-format PPM files with any maxval */
249
89.7k
{
250
89.7k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
251
89.7k
  FILE *infile = source->pub.input_file;
252
89.7k
  register JSAMPROW ptr;
253
89.7k
  register JSAMPLE *rescale = source->rescale;
254
89.7k
  JDIMENSION col;
255
89.7k
  unsigned int maxval = source->maxval;
256
89.7k
  register int rindex = rgb_red[cinfo->in_color_space];
257
89.7k
  register int gindex = rgb_green[cinfo->in_color_space];
258
89.7k
  register int bindex = rgb_blue[cinfo->in_color_space];
259
89.7k
  register int aindex = alpha_index[cinfo->in_color_space];
260
89.7k
  register int ps = rgb_pixelsize[cinfo->in_color_space];
261
262
89.7k
  ptr = source->pub.buffer[0];
263
89.7k
  if (maxval == MAXJSAMPLE) {
264
29.3k
    if (aindex >= 0)
265
3.98k
      RGB_READ_LOOP((JSAMPLE)read_pbm_integer(cinfo, infile, maxval),
266
29.3k
                    ptr[aindex] = MAXJSAMPLE;)
267
25.4k
    else
268
25.4k
      RGB_READ_LOOP((JSAMPLE)read_pbm_integer(cinfo, infile, maxval), {})
269
60.3k
  } else {
270
60.3k
    if (aindex >= 0)
271
8.17k
      RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)],
272
60.3k
                    ptr[aindex] = MAXJSAMPLE;)
273
52.1k
    else
274
52.1k
      RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], {})
275
60.3k
  }
276
89.7k
  return 1;
277
89.7k
}
278
279
280
METHODDEF(JDIMENSION)
281
get_text_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
282
/* This version is for reading text-format PPM files with any maxval and
283
   converting to CMYK */
284
12.1k
{
285
12.1k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
286
12.1k
  FILE *infile = source->pub.input_file;
287
12.1k
  register JSAMPROW ptr;
288
12.1k
  register JSAMPLE *rescale = source->rescale;
289
12.1k
  JDIMENSION col;
290
12.1k
  unsigned int maxval = source->maxval;
291
292
12.1k
  ptr = source->pub.buffer[0];
293
12.1k
  if (maxval == MAXJSAMPLE) {
294
14.0k
    for (col = cinfo->image_width; col > 0; col--) {
295
10.0k
      JSAMPLE r = (JSAMPLE)read_pbm_integer(cinfo, infile, maxval);
296
10.0k
      JSAMPLE g = (JSAMPLE)read_pbm_integer(cinfo, infile, maxval);
297
10.0k
      JSAMPLE b = (JSAMPLE)read_pbm_integer(cinfo, infile, maxval);
298
10.0k
      rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
299
10.0k
      ptr += 4;
300
10.0k
    }
301
8.17k
  } else {
302
21.9k
    for (col = cinfo->image_width; col > 0; col--) {
303
13.7k
      JSAMPLE r = rescale[read_pbm_integer(cinfo, infile, maxval)];
304
13.7k
      JSAMPLE g = rescale[read_pbm_integer(cinfo, infile, maxval)];
305
13.7k
      JSAMPLE b = rescale[read_pbm_integer(cinfo, infile, maxval)];
306
13.7k
      rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
307
13.7k
      ptr += 4;
308
13.7k
    }
309
8.17k
  }
310
12.1k
  return 1;
311
12.1k
}
312
313
314
METHODDEF(JDIMENSION)
315
get_scaled_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
316
/* This version is for reading raw-byte-format PGM files with any maxval */
317
42.1M
{
318
42.1M
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
319
42.1M
  register JSAMPROW ptr;
320
42.1M
  register U_CHAR *bufferptr;
321
42.1M
  register JSAMPLE *rescale = source->rescale;
322
42.1M
  JDIMENSION col;
323
324
42.1M
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
325
805
    ERREXIT(cinfo, JERR_INPUT_EOF);
326
42.1M
  ptr = source->pub.buffer[0];
327
42.1M
  bufferptr = source->iobuffer;
328
135M
  for (col = cinfo->image_width; col > 0; col--) {
329
93.0M
    *ptr++ = rescale[UCH(*bufferptr++)];
330
93.0M
  }
331
42.1M
  return 1;
332
42.1M
}
333
334
335
METHODDEF(JDIMENSION)
336
get_gray_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
337
/* This version is for reading raw-byte-format PGM files with any maxval
338
   and converting to extended RGB */
339
232M
{
340
232M
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
341
232M
  register JSAMPROW ptr;
342
232M
  register U_CHAR *bufferptr;
343
232M
  register JSAMPLE *rescale = source->rescale;
344
232M
  JDIMENSION col;
345
232M
  unsigned int maxval = source->maxval;
346
232M
  register int rindex = rgb_red[cinfo->in_color_space];
347
232M
  register int gindex = rgb_green[cinfo->in_color_space];
348
232M
  register int bindex = rgb_blue[cinfo->in_color_space];
349
232M
  register int aindex = alpha_index[cinfo->in_color_space];
350
232M
  register int ps = rgb_pixelsize[cinfo->in_color_space];
351
352
232M
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
353
4.22k
    ERREXIT(cinfo, JERR_INPUT_EOF);
354
232M
  ptr = source->pub.buffer[0];
355
232M
  bufferptr = source->iobuffer;
356
232M
  if (maxval == MAXJSAMPLE) {
357
21.7M
    if (aindex >= 0)
358
827k
      GRAY_RGB_READ_LOOP(*bufferptr++, ptr[aindex] = MAXJSAMPLE;)
359
20.9M
    else
360
20.9M
      GRAY_RGB_READ_LOOP(*bufferptr++, {})
361
210M
  } else {
362
210M
    if (aindex >= 0)
363
30.1M
      GRAY_RGB_READ_LOOP(rescale[UCH(*bufferptr++)], ptr[aindex] = MAXJSAMPLE;)
364
180M
    else
365
180M
      GRAY_RGB_READ_LOOP(rescale[UCH(*bufferptr++)], {})
366
210M
  }
367
232M
  return 1;
368
232M
}
369
370
371
METHODDEF(JDIMENSION)
372
get_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
373
/* This version is for reading raw-byte-format PGM files with any maxval
374
   and converting to CMYK */
375
31.0M
{
376
31.0M
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
377
31.0M
  register JSAMPROW ptr;
378
31.0M
  register U_CHAR *bufferptr;
379
31.0M
  register JSAMPLE *rescale = source->rescale;
380
31.0M
  JDIMENSION col;
381
31.0M
  unsigned int maxval = source->maxval;
382
383
31.0M
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
384
595
    ERREXIT(cinfo, JERR_INPUT_EOF);
385
31.0M
  ptr = source->pub.buffer[0];
386
31.0M
  bufferptr = source->iobuffer;
387
31.0M
  if (maxval == MAXJSAMPLE) {
388
5.43M
    for (col = cinfo->image_width; col > 0; col--) {
389
4.60M
      JSAMPLE gray = *bufferptr++;
390
4.60M
      rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
391
4.60M
      ptr += 4;
392
4.60M
    }
393
30.1M
  } else {
394
93.3M
    for (col = cinfo->image_width; col > 0; col--) {
395
63.1M
      JSAMPLE gray = rescale[UCH(*bufferptr++)];
396
63.1M
      rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
397
63.1M
      ptr += 4;
398
63.1M
    }
399
30.1M
  }
400
31.0M
  return 1;
401
31.0M
}
402
403
404
METHODDEF(JDIMENSION)
405
get_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
406
/* This version is for reading raw-byte-format PPM files with any maxval */
407
2.92M
{
408
2.92M
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
409
2.92M
  register JSAMPROW ptr;
410
2.92M
  register U_CHAR *bufferptr;
411
2.92M
  register JSAMPLE *rescale = source->rescale;
412
2.92M
  JDIMENSION col;
413
2.92M
  unsigned int maxval = source->maxval;
414
2.92M
  register int rindex = rgb_red[cinfo->in_color_space];
415
2.92M
  register int gindex = rgb_green[cinfo->in_color_space];
416
2.92M
  register int bindex = rgb_blue[cinfo->in_color_space];
417
2.92M
  register int aindex = alpha_index[cinfo->in_color_space];
418
2.92M
  register int ps = rgb_pixelsize[cinfo->in_color_space];
419
420
2.92M
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
421
6.48k
    ERREXIT(cinfo, JERR_INPUT_EOF);
422
2.92M
  ptr = source->pub.buffer[0];
423
2.92M
  bufferptr = source->iobuffer;
424
2.92M
  if (maxval == MAXJSAMPLE) {
425
190k
    if (aindex >= 0)
426
20.1k
      RGB_READ_LOOP(*bufferptr++, ptr[aindex] = MAXJSAMPLE;)
427
170k
    else
428
170k
      RGB_READ_LOOP(*bufferptr++, {})
429
2.73M
  } else {
430
2.73M
    if (aindex >= 0)
431
462k
      RGB_READ_LOOP(rescale[UCH(*bufferptr++)], ptr[aindex] = MAXJSAMPLE;)
432
2.27M
    else
433
2.27M
      RGB_READ_LOOP(rescale[UCH(*bufferptr++)], {})
434
2.73M
  }
435
2.92M
  return 1;
436
2.92M
}
437
438
439
METHODDEF(JDIMENSION)
440
get_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
441
/* This version is for reading raw-byte-format PPM files with any maxval and
442
   converting to CMYK */
443
483k
{
444
483k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
445
483k
  register JSAMPROW ptr;
446
483k
  register U_CHAR *bufferptr;
447
483k
  register JSAMPLE *rescale = source->rescale;
448
483k
  JDIMENSION col;
449
483k
  unsigned int maxval = source->maxval;
450
451
483k
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
452
968
    ERREXIT(cinfo, JERR_INPUT_EOF);
453
483k
  ptr = source->pub.buffer[0];
454
483k
  bufferptr = source->iobuffer;
455
483k
  if (maxval == MAXJSAMPLE) {
456
743k
    for (col = cinfo->image_width; col > 0; col--) {
457
723k
      JSAMPLE r = *bufferptr++;
458
723k
      JSAMPLE g = *bufferptr++;
459
723k
      JSAMPLE b = *bufferptr++;
460
723k
      rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
461
723k
      ptr += 4;
462
723k
    }
463
463k
  } else {
464
3.99M
    for (col = cinfo->image_width; col > 0; col--) {
465
3.53M
      JSAMPLE r = rescale[UCH(*bufferptr++)];
466
3.53M
      JSAMPLE g = rescale[UCH(*bufferptr++)];
467
3.53M
      JSAMPLE b = rescale[UCH(*bufferptr++)];
468
3.53M
      rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
469
3.53M
      ptr += 4;
470
3.53M
    }
471
463k
  }
472
483k
  return 1;
473
483k
}
474
475
476
METHODDEF(JDIMENSION)
477
get_raw_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
478
/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
479
 * In this case we just read right into the JSAMPLE buffer!
480
 * Note that same code works for PPM and PGM files.
481
 */
482
4.39M
{
483
4.39M
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
484
485
4.39M
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
486
584
    ERREXIT(cinfo, JERR_INPUT_EOF);
487
4.39M
  return 1;
488
4.39M
}
489
490
491
METHODDEF(JDIMENSION)
492
get_word_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
493
/* This version is for reading raw-word-format PGM files with any maxval */
494
215k
{
495
215k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
496
215k
  register JSAMPROW ptr;
497
215k
  register U_CHAR *bufferptr;
498
215k
  register JSAMPLE *rescale = source->rescale;
499
215k
  JDIMENSION col;
500
215k
  unsigned int maxval = source->maxval;
501
502
215k
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
503
646
    ERREXIT(cinfo, JERR_INPUT_EOF);
504
215k
  ptr = source->pub.buffer[0];
505
215k
  bufferptr = source->iobuffer;
506
812k
  for (col = cinfo->image_width; col > 0; col--) {
507
596k
    register unsigned int temp;
508
596k
    temp  = UCH(*bufferptr++) << 8;
509
596k
    temp |= UCH(*bufferptr++);
510
596k
    if (temp > maxval)
511
314
      ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
512
596k
    *ptr++ = rescale[temp];
513
596k
  }
514
215k
  return 1;
515
215k
}
516
517
518
METHODDEF(JDIMENSION)
519
get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
520
/* This version is for reading raw-word-format PPM files with any maxval */
521
94.8k
{
522
94.8k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
523
94.8k
  register JSAMPROW ptr;
524
94.8k
  register U_CHAR *bufferptr;
525
94.8k
  register JSAMPLE *rescale = source->rescale;
526
94.8k
  JDIMENSION col;
527
94.8k
  unsigned int maxval = source->maxval;
528
94.8k
  register int rindex = rgb_red[cinfo->in_color_space];
529
94.8k
  register int gindex = rgb_green[cinfo->in_color_space];
530
94.8k
  register int bindex = rgb_blue[cinfo->in_color_space];
531
94.8k
  register int aindex = alpha_index[cinfo->in_color_space];
532
94.8k
  register int ps = rgb_pixelsize[cinfo->in_color_space];
533
534
94.8k
  if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
535
3.37k
    ERREXIT(cinfo, JERR_INPUT_EOF);
536
94.8k
  ptr = source->pub.buffer[0];
537
94.8k
  bufferptr = source->iobuffer;
538
351k
  for (col = cinfo->image_width; col > 0; col--) {
539
256k
    register unsigned int temp;
540
256k
    temp  = UCH(*bufferptr++) << 8;
541
256k
    temp |= UCH(*bufferptr++);
542
256k
    if (temp > maxval)
543
1.33k
      ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
544
256k
    ptr[rindex] = rescale[temp];
545
256k
    temp  = UCH(*bufferptr++) << 8;
546
256k
    temp |= UCH(*bufferptr++);
547
256k
    if (temp > maxval)
548
1.13k
      ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
549
256k
    ptr[gindex] = rescale[temp];
550
256k
    temp  = UCH(*bufferptr++) << 8;
551
256k
    temp |= UCH(*bufferptr++);
552
256k
    if (temp > maxval)
553
1.08k
      ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
554
256k
    ptr[bindex] = rescale[temp];
555
256k
    if (aindex >= 0)
556
44.0k
      ptr[aindex] = MAXJSAMPLE;
557
256k
    ptr += ps;
558
256k
  }
559
94.8k
  return 1;
560
94.8k
}
561
562
563
/*
564
 * Read the file header; return image size and component count.
565
 */
566
567
METHODDEF(void)
568
start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
569
61.8k
{
570
61.8k
  ppm_source_ptr source = (ppm_source_ptr)sinfo;
571
61.8k
  int c;
572
61.8k
  unsigned int w, h, maxval;
573
61.8k
  boolean need_iobuffer, use_raw_buffer, need_rescale;
574
575
61.8k
  if (getc(source->pub.input_file) != 'P')
576
0
    ERREXIT(cinfo, JERR_PPM_NOT);
577
578
61.8k
  c = getc(source->pub.input_file); /* subformat discriminator character */
579
580
  /* detect unsupported variants (ie, PBM) before trying to read header */
581
61.8k
  switch (c) {
582
5.17k
  case '2':                     /* it's a text-format PGM file */
583
10.9k
  case '3':                     /* it's a text-format PPM file */
584
47.5k
  case '5':                     /* it's a raw-format PGM file */
585
61.7k
  case '6':                     /* it's a raw-format PPM file */
586
61.7k
    break;
587
45
  default:
588
45
    ERREXIT(cinfo, JERR_PPM_NOT);
589
45
    break;
590
61.8k
  }
591
592
  /* fetch the remaining header info */
593
61.7k
  w = read_pbm_integer(cinfo, source->pub.input_file, 65535);
594
61.7k
  h = read_pbm_integer(cinfo, source->pub.input_file, 65535);
595
61.7k
  maxval = read_pbm_integer(cinfo, source->pub.input_file, 65535);
596
597
61.7k
  if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
598
103
    ERREXIT(cinfo, JERR_PPM_NOT);
599
61.7k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
600
61.7k
  if (sinfo->max_pixels && (unsigned long long)w * h > sinfo->max_pixels)
601
940
    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
602
61.7k
#endif
603
604
61.7k
  cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
605
61.7k
  cinfo->image_width = (JDIMENSION)w;
606
61.7k
  cinfo->image_height = (JDIMENSION)h;
607
61.7k
  source->maxval = maxval;
608
609
  /* initialize flags to most common settings */
610
61.7k
  need_iobuffer = TRUE;         /* do we need an I/O buffer? */
611
61.7k
  use_raw_buffer = FALSE;       /* do we map input buffer onto I/O buffer? */
612
61.7k
  need_rescale = TRUE;          /* do we need a rescale array? */
613
614
61.7k
  switch (c) {
615
3.64k
  case '2':                     /* it's a text-format PGM file */
616
3.64k
    if (cinfo->in_color_space == JCS_UNKNOWN ||
617
3.64k
        cinfo->in_color_space == JCS_RGB)
618
438
      cinfo->in_color_space = JCS_GRAYSCALE;
619
3.64k
    TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
620
3.64k
    if (cinfo->in_color_space == JCS_GRAYSCALE)
621
931
      source->pub.get_pixel_rows = get_text_gray_row;
622
2.71k
    else if (IsExtRGB(cinfo->in_color_space))
623
2.46k
      source->pub.get_pixel_rows = get_text_gray_rgb_row;
624
245
    else if (cinfo->in_color_space == JCS_CMYK)
625
245
      source->pub.get_pixel_rows = get_text_gray_cmyk_row;
626
0
    else
627
0
      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
628
3.64k
    need_iobuffer = FALSE;
629
3.64k
    break;
630
631
4.33k
  case '3':                     /* it's a text-format PPM file */
632
4.33k
    if (cinfo->in_color_space == JCS_UNKNOWN)
633
0
      cinfo->in_color_space = JCS_EXT_RGB;
634
4.33k
    TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
635
4.33k
    if (IsExtRGB(cinfo->in_color_space))
636
3.40k
      source->pub.get_pixel_rows = get_text_rgb_row;
637
933
    else if (cinfo->in_color_space == JCS_CMYK)
638
341
      source->pub.get_pixel_rows = get_text_rgb_cmyk_row;
639
592
    else
640
592
      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
641
4.33k
    need_iobuffer = FALSE;
642
4.33k
    break;
643
644
34.9k
  case '5':                     /* it's a raw-format PGM file */
645
34.9k
    if (cinfo->in_color_space == JCS_UNKNOWN ||
646
34.9k
        cinfo->in_color_space == JCS_RGB)
647
938
      cinfo->in_color_space = JCS_GRAYSCALE;
648
34.9k
    TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
649
34.9k
    if (maxval > 255) {
650
2.39k
      if (cinfo->in_color_space == JCS_GRAYSCALE)
651
609
        source->pub.get_pixel_rows = get_word_gray_row;
652
1.79k
      else
653
1.79k
        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
654
32.5k
    } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
655
32.5k
               cinfo->in_color_space == JCS_GRAYSCALE) {
656
656
      source->pub.get_pixel_rows = get_raw_row;
657
656
      use_raw_buffer = TRUE;
658
656
      need_rescale = FALSE;
659
31.8k
    } else {
660
31.8k
      if (cinfo->in_color_space == JCS_GRAYSCALE)
661
5.01k
        source->pub.get_pixel_rows = get_scaled_gray_row;
662
26.8k
      else if (IsExtRGB(cinfo->in_color_space))
663
25.0k
        source->pub.get_pixel_rows = get_gray_rgb_row;
664
1.76k
      else if (cinfo->in_color_space == JCS_CMYK)
665
1.76k
        source->pub.get_pixel_rows = get_gray_cmyk_row;
666
0
      else
667
0
        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
668
31.8k
    }
669
34.9k
    break;
670
671
12.6k
  case '6':                     /* it's a raw-format PPM file */
672
12.6k
    if (cinfo->in_color_space == JCS_UNKNOWN)
673
0
      cinfo->in_color_space = JCS_EXT_RGB;
674
12.6k
    TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
675
12.6k
    if (maxval > 255) {
676
3.45k
      if (IsExtRGB(cinfo->in_color_space))
677
2.74k
        source->pub.get_pixel_rows = get_word_rgb_row;
678
703
      else
679
703
        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
680
9.18k
    } else if (maxval == MAXJSAMPLE && sizeof(JSAMPLE) == sizeof(U_CHAR) &&
681
9.18k
#if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3
682
9.18k
               (cinfo->in_color_space == JCS_EXT_RGB ||
683
2.10k
                cinfo->in_color_space == JCS_RGB)) {
684
#else
685
               cinfo->in_color_space == JCS_EXT_RGB) {
686
#endif
687
379
      source->pub.get_pixel_rows = get_raw_row;
688
379
      use_raw_buffer = TRUE;
689
379
      need_rescale = FALSE;
690
8.80k
    } else {
691
8.80k
      if (IsExtRGB(cinfo->in_color_space))
692
6.97k
        source->pub.get_pixel_rows = get_rgb_row;
693
1.83k
      else if (cinfo->in_color_space == JCS_CMYK)
694
634
        source->pub.get_pixel_rows = get_rgb_cmyk_row;
695
1.20k
      else
696
1.20k
        ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
697
8.80k
    }
698
12.6k
    break;
699
61.7k
  }
700
701
51.2k
  if (IsExtRGB(cinfo->in_color_space))
702
41.0k
    cinfo->input_components = rgb_pixelsize[cinfo->in_color_space];
703
10.2k
  else if (cinfo->in_color_space == JCS_GRAYSCALE)
704
7.21k
    cinfo->input_components = 1;
705
2.98k
  else if (cinfo->in_color_space == JCS_CMYK)
706
2.98k
    cinfo->input_components = 4;
707
708
  /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
709
51.2k
  if (need_iobuffer) {
710
43.8k
    if (c == '6')
711
10.7k
      source->buffer_width = (size_t)w * 3 *
712
10.7k
        ((maxval <= 255) ? sizeof(U_CHAR) : (2 * sizeof(U_CHAR)));
713
33.1k
    else
714
33.1k
      source->buffer_width = (size_t)w *
715
33.1k
        ((maxval <= 255) ? sizeof(U_CHAR) : (2 * sizeof(U_CHAR)));
716
43.8k
    source->iobuffer = (U_CHAR *)
717
43.8k
      (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
718
43.8k
                                  source->buffer_width);
719
43.8k
  }
720
721
  /* Create compressor input buffer. */
722
51.2k
  if (use_raw_buffer) {
723
    /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
724
    /* Synthesize a JSAMPARRAY pointer structure */
725
1.03k
    source->pixrow = (JSAMPROW)source->iobuffer;
726
1.03k
    source->pub.buffer = &source->pixrow;
727
1.03k
    source->pub.buffer_height = 1;
728
50.2k
  } else {
729
    /* Need to translate anyway, so make a separate sample buffer. */
730
50.2k
    source->pub.buffer = (*cinfo->mem->alloc_sarray)
731
50.2k
      ((j_common_ptr)cinfo, JPOOL_IMAGE,
732
50.2k
       (JDIMENSION)w * cinfo->input_components, (JDIMENSION)1);
733
50.2k
    source->pub.buffer_height = 1;
734
50.2k
  }
735
736
  /* Compute the rescaling array if required. */
737
51.2k
  if (need_rescale) {
738
50.2k
    long val, half_maxval;
739
740
    /* On 16-bit-int machines we have to be careful of maxval = 65535 */
741
50.2k
    source->rescale = (JSAMPLE *)
742
50.2k
      (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
743
50.2k
                                  (size_t)(((long)MAX(maxval, 255) + 1L) *
744
50.2k
                                           sizeof(JSAMPLE)));
745
50.2k
    MEMZERO(source->rescale, (size_t)(((long)MAX(maxval, 255) + 1L) *
746
50.2k
                                      sizeof(JSAMPLE)));
747
50.2k
    half_maxval = maxval / 2;
748
57.5M
    for (val = 0; val <= (long)maxval; val++) {
749
      /* The multiplication here must be done in 32 bits to avoid overflow */
750
57.5M
      source->rescale[val] = (JSAMPLE)((val * MAXJSAMPLE + half_maxval) /
751
57.5M
                                        maxval);
752
57.5M
    }
753
50.2k
  }
754
51.2k
}
755
756
757
/*
758
 * Finish up at the end of the file.
759
 */
760
761
METHODDEF(void)
762
finish_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
763
93.4k
{
764
  /* no work */
765
93.4k
}
766
767
768
/*
769
 * The module selection routine for PPM format input.
770
 */
771
772
GLOBAL(cjpeg_source_ptr)
773
jinit_read_ppm(j_compress_ptr cinfo)
774
61.8k
{
775
61.8k
  ppm_source_ptr source;
776
777
  /* Create module interface object */
778
61.8k
  source = (ppm_source_ptr)
779
61.8k
    (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
780
61.8k
                                sizeof(ppm_source_struct));
781
  /* Fill in method ptrs, except get_pixel_rows which start_input sets */
782
61.8k
  source->pub.start_input = start_input_ppm;
783
61.8k
  source->pub.finish_input = finish_input_ppm;
784
61.8k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
785
61.8k
  source->pub.max_pixels = 0;
786
61.8k
#endif
787
788
61.8k
  return (cjpeg_source_ptr)source;
789
61.8k
}
790
791
#endif /* PPM_SUPPORTED */