ReactOS 0.4.16-dev-125-g798ea90
rdppm.c
Go to the documentation of this file.
1/*
2 * rdppm.c
3 *
4 * Copyright (C) 1991-1997, Thomas G. Lane.
5 * Modified 2009-2019 by Bill Allombert, Guido Vollbeding.
6 * This file is part of the Independent JPEG Group's software.
7 * For conditions of distribution and use, see the accompanying README file.
8 *
9 * This file contains routines to read input images in PPM/PGM format.
10 * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
11 * The PBMPLUS library is NOT required to compile this software
12 * (but it is highly useful as a set of PPM image manipulation programs).
13 *
14 * These routines may need modification for non-Unix environments or
15 * specialized applications. As they stand, they assume input from
16 * an ordinary stdio stream. They further assume that reading begins
17 * at the start of the file; start_input may need work if the
18 * user interface has already read some data (e.g., to determine that
19 * the file is indeed PPM format).
20 */
21
22/* Portions of this code are based on the PBMPLUS library, which is:
23**
24** Copyright (C) 1988 by Jef Poskanzer.
25**
26** Permission to use, copy, modify, and distribute this software and its
27** documentation for any purpose and without fee is hereby granted, provided
28** that the above copyright notice appear in all copies and that both that
29** copyright notice and this permission notice appear in supporting
30** documentation. This software is provided "as is" without express or
31** implied warranty.
32*/
33
34#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
35
36#ifdef PPM_SUPPORTED
37
38
39/* Macros to deal with unsigned chars as efficiently as compiler allows */
40
41#ifdef HAVE_UNSIGNED_CHAR
42typedef unsigned char U_CHAR;
43#define UCH(x) ((int) (x))
44#else /* !HAVE_UNSIGNED_CHAR */
45typedef char U_CHAR;
46#ifdef CHAR_IS_UNSIGNED
47#define UCH(x) ((int) (x))
48#else
49#define UCH(x) ((int) (x) & 0xFF)
50#endif
51#endif /* HAVE_UNSIGNED_CHAR */
52
53
54#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
55
56
57/*
58 * On most systems, reading individual bytes with getc() is drastically less
59 * efficient than buffering a row at a time with fread(). On PCs, we must
60 * allocate the buffer in near data space, because we are assuming small-data
61 * memory model, wherein fread() can't reach far memory. If you need to
62 * process very wide images on a PC, you might have to compile in large-memory
63 * model, or else replace fread() with a getc() loop --- which will be much
64 * slower.
65 */
66
67
68/* Private version of data source object */
69
70typedef struct {
71 struct cjpeg_source_struct pub; /* public fields */
72
73 U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */
74 JSAMPROW pixrow; /* FAR pointer to same */
75 size_t buffer_width; /* width of I/O buffer */
76 JSAMPLE *rescale; /* => maxval-remapping array, or NULL */
77 unsigned int maxval;
78} ppm_source_struct;
79
80typedef ppm_source_struct * ppm_source_ptr;
81
82
83LOCAL(int)
84pbm_getc (FILE * infile)
85/* Read next char, skipping over any comments */
86/* A comment/newline sequence is returned as a newline */
87{
88 register int ch;
89
90 ch = getc(infile);
91 if (ch == '#') {
92 do {
93 ch = getc(infile);
94 } while (ch != '\n' && ch != EOF);
95 }
96 return ch;
97}
98
99
100LOCAL(unsigned int)
101read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
102/* Read an unsigned decimal integer from the PPM file */
103/* Swallows one trailing character after the integer */
104/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
105/* This should not be a problem in practice. */
106{
107 register int ch;
108 register unsigned int val;
109
110 /* Skip any leading whitespace */
111 do {
112 ch = pbm_getc(infile);
113 if (ch == EOF)
114 ERREXIT(cinfo, JERR_INPUT_EOF);
115 } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
116
117 if (ch < '0' || ch > '9')
118 ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
119
120 val = ch - '0';
121 while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
122 val *= 10;
123 val += ch - '0';
124 }
125 return val;
126}
127
128
129/*
130 * Read one row of pixels.
131 *
132 * We provide several different versions depending on input file format.
133 * In all cases, input is scaled to the size of JSAMPLE.
134 *
135 * A really fast path is provided for reading byte/sample raw files with
136 * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
137 */
138
139
141get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
142/* This version is for reading text-format PGM files with any maxval */
143{
144 ppm_source_ptr source = (ppm_source_ptr) sinfo;
145 FILE * infile = source->pub.input_file;
146 register JSAMPROW ptr;
147 register JSAMPLE *rescale = source->rescale;
148 unsigned int maxval = source->maxval;
149 JDIMENSION col;
150
151 ptr = source->pub.buffer[0];
152 for (col = cinfo->image_width; col > 0; col--) {
153 register unsigned int temp;
154 temp = read_pbm_integer(cinfo, infile);
155 if (temp > maxval)
156 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
157 *ptr++ = rescale[temp];
158 }
159 return 1;
160}
161
162
164get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
165/* This version is for reading text-format PPM files with any maxval */
166{
167 ppm_source_ptr source = (ppm_source_ptr) sinfo;
168 FILE * infile = source->pub.input_file;
169 register JSAMPROW ptr;
170 register JSAMPLE *rescale = source->rescale;
171 unsigned int maxval = source->maxval;
172 JDIMENSION col;
173
174 ptr = source->pub.buffer[0];
175 for (col = cinfo->image_width; col > 0; col--) {
176 register unsigned int temp;
177 temp = read_pbm_integer(cinfo, infile);
178 if (temp > maxval)
179 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
180 *ptr++ = rescale[temp];
181 temp = read_pbm_integer(cinfo, infile);
182 if (temp > maxval)
183 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
184 *ptr++ = rescale[temp];
185 temp = read_pbm_integer(cinfo, infile);
186 if (temp > maxval)
187 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
188 *ptr++ = rescale[temp];
189 }
190 return 1;
191}
192
193
195get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
196/* This version is for reading raw-byte-format PGM files with any maxval */
197{
198 ppm_source_ptr source = (ppm_source_ptr) sinfo;
199 register JSAMPROW ptr;
200 register U_CHAR * bufferptr;
201 register JSAMPLE *rescale = source->rescale;
202 unsigned int maxval = source->maxval;
203 JDIMENSION col;
204
205 if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
206 ERREXIT(cinfo, JERR_INPUT_EOF);
207 ptr = source->pub.buffer[0];
208 bufferptr = source->iobuffer;
209 for (col = cinfo->image_width; col > 0; col--) {
210 register unsigned int temp;
211 temp = (unsigned int) UCH(*bufferptr++);
212 if (temp > maxval)
213 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
214 *ptr++ = rescale[temp];
215 }
216 return 1;
217}
218
219
221get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
222/* This version is for reading raw-byte-format PPM files with any maxval */
223{
224 ppm_source_ptr source = (ppm_source_ptr) sinfo;
225 register JSAMPROW ptr;
226 register U_CHAR * bufferptr;
227 register JSAMPLE *rescale = source->rescale;
228 unsigned int maxval = source->maxval;
229 JDIMENSION col;
230
231 if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
232 ERREXIT(cinfo, JERR_INPUT_EOF);
233 ptr = source->pub.buffer[0];
234 bufferptr = source->iobuffer;
235 for (col = cinfo->image_width; col > 0; col--) {
236 register unsigned int temp;
237 temp = (unsigned int) UCH(*bufferptr++);
238 if (temp > maxval)
239 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
240 *ptr++ = rescale[temp];
241 temp = (unsigned int) UCH(*bufferptr++);
242 if (temp > maxval)
243 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
244 *ptr++ = rescale[temp];
245 temp = (unsigned int) UCH(*bufferptr++);
246 if (temp > maxval)
247 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
248 *ptr++ = rescale[temp];
249 }
250 return 1;
251}
252
253
255get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
256/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
257 * In this case we just read right into the JSAMPLE buffer!
258 * Note that same code works for PPM and PGM files.
259 */
260{
261 ppm_source_ptr source = (ppm_source_ptr) sinfo;
262
263 if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
264 ERREXIT(cinfo, JERR_INPUT_EOF);
265 return 1;
266}
267
268
270get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
271/* This version is for reading raw-word-format PGM files with any maxval */
272{
273 ppm_source_ptr source = (ppm_source_ptr) sinfo;
274 register JSAMPROW ptr;
275 register U_CHAR * bufferptr;
276 register JSAMPLE *rescale = source->rescale;
277 unsigned int maxval = source->maxval;
278 JDIMENSION col;
279
280 if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
281 ERREXIT(cinfo, JERR_INPUT_EOF);
282 ptr = source->pub.buffer[0];
283 bufferptr = source->iobuffer;
284 for (col = cinfo->image_width; col > 0; col--) {
285 register unsigned int temp;
286 temp = ((unsigned int) UCH(*bufferptr++)) << 8;
287 temp |= (unsigned int) UCH(*bufferptr++);
288 if (temp > maxval)
289 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
290 *ptr++ = rescale[temp];
291 }
292 return 1;
293}
294
295
297get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
298/* This version is for reading raw-word-format PPM files with any maxval */
299{
300 ppm_source_ptr source = (ppm_source_ptr) sinfo;
301 register JSAMPROW ptr;
302 register U_CHAR * bufferptr;
303 register JSAMPLE *rescale = source->rescale;
304 unsigned int maxval = source->maxval;
305 JDIMENSION col;
306
307 if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
308 ERREXIT(cinfo, JERR_INPUT_EOF);
309 ptr = source->pub.buffer[0];
310 bufferptr = source->iobuffer;
311 for (col = cinfo->image_width; col > 0; col--) {
312 register unsigned int temp;
313 temp = ((unsigned int) UCH(*bufferptr++)) << 8;
314 temp |= (unsigned int) UCH(*bufferptr++);
315 if (temp > maxval)
316 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
317 *ptr++ = rescale[temp];
318 temp = ((unsigned int) UCH(*bufferptr++)) << 8;
319 temp |= (unsigned int) UCH(*bufferptr++);
320 if (temp > maxval)
321 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
322 *ptr++ = rescale[temp];
323 temp = ((unsigned int) UCH(*bufferptr++)) << 8;
324 temp |= (unsigned int) UCH(*bufferptr++);
325 if (temp > maxval)
326 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
327 *ptr++ = rescale[temp];
328 }
329 return 1;
330}
331
332
333/*
334 * Read the file header; return image size and component count.
335 */
336
337METHODDEF(void)
338start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
339{
340 ppm_source_ptr source = (ppm_source_ptr) sinfo;
341 int c;
342 unsigned int w, h, maxval;
343 boolean need_iobuffer, use_raw_buffer, need_rescale;
344
345 if (getc(source->pub.input_file) != 'P')
346 ERREXIT(cinfo, JERR_PPM_NOT);
347
348 c = getc(source->pub.input_file); /* subformat discriminator character */
349
350 /* detect unsupported variants (ie, PBM) before trying to read header */
351 switch (c) {
352 case '2': /* it's a text-format PGM file */
353 case '3': /* it's a text-format PPM file */
354 case '5': /* it's a raw-format PGM file */
355 case '6': /* it's a raw-format PPM file */
356 break;
357 default:
358 ERREXIT(cinfo, JERR_PPM_NOT);
359 }
360
361 /* fetch the remaining header info */
362 w = read_pbm_integer(cinfo, source->pub.input_file);
363 h = read_pbm_integer(cinfo, source->pub.input_file);
364 maxval = read_pbm_integer(cinfo, source->pub.input_file);
365
366 if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
367 ERREXIT(cinfo, JERR_PPM_NOT);
368
369 if (((long) w >> 24) || /* sanity check for buffer allocation below */
370 ((long) maxval >> 16)) /* support max 16-bit (2-byte) sample values */
371 ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
372
373 cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
374 cinfo->image_width = (JDIMENSION) w;
375 cinfo->image_height = (JDIMENSION) h;
376 source->maxval = maxval;
377
378 /* initialize flags to most common settings */
379 need_iobuffer = TRUE; /* do we need an I/O buffer? */
380 use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */
381 need_rescale = TRUE; /* do we need a rescale array? */
382
383 switch (c) {
384 case '2': /* it's a text-format PGM file */
385 cinfo->input_components = 1;
387 TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
388 source->pub.get_pixel_rows = get_text_gray_row;
389 need_iobuffer = FALSE;
390 break;
391
392 case '3': /* it's a text-format PPM file */
393 cinfo->input_components = 3;
394 cinfo->in_color_space = JCS_RGB;
395 TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
396 source->pub.get_pixel_rows = get_text_rgb_row;
397 need_iobuffer = FALSE;
398 break;
399
400 case '5': /* it's a raw-format PGM file */
401 cinfo->input_components = 1;
403 TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
404 if (maxval > 255) {
405 source->pub.get_pixel_rows = get_word_gray_row;
406 } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
407 source->pub.get_pixel_rows = get_raw_row;
408 use_raw_buffer = TRUE;
409 need_rescale = FALSE;
410 } else {
411 source->pub.get_pixel_rows = get_scaled_gray_row;
412 }
413 break;
414
415 case '6': /* it's a raw-format PPM file */
416 cinfo->input_components = 3;
417 cinfo->in_color_space = JCS_RGB;
418 TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
419 if (maxval > 255) {
420 source->pub.get_pixel_rows = get_word_rgb_row;
421 } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
422 source->pub.get_pixel_rows = get_raw_row;
423 use_raw_buffer = TRUE;
424 need_rescale = FALSE;
425 } else {
426 source->pub.get_pixel_rows = get_scaled_rgb_row;
427 }
428 break;
429 }
430
431 /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
432 if (need_iobuffer) {
433 source->buffer_width = (size_t) w * cinfo->input_components *
434 ((maxval <= 255) ? SIZEOF(U_CHAR) : (2 * SIZEOF(U_CHAR)));
435 source->iobuffer = (U_CHAR *) (*cinfo->mem->alloc_small)
436 ((j_common_ptr) cinfo, JPOOL_IMAGE, source->buffer_width);
437 }
438
439 /* Create compressor input buffer. */
440 if (use_raw_buffer) {
441 /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
442 /* Synthesize a JSAMPARRAY pointer structure */
443 /* Cast here implies near->far pointer conversion on PCs */
444 source->pixrow = (JSAMPROW) source->iobuffer;
445 source->pub.buffer = & source->pixrow;
446 source->pub.buffer_height = 1;
447 } else {
448 /* Need to translate anyway, so make a separate sample buffer. */
449 source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,
451 source->pub.buffer_height = 1;
452 }
453
454 /* Compute the rescaling array if required. */
455 if (need_rescale) {
456 INT32 val, half_maxval;
457
458 /* On 16-bit-int machines we have to be careful of maxval = 65535 */
459 source->rescale = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
460 JPOOL_IMAGE, ((size_t) maxval + (size_t) 1) * SIZEOF(JSAMPLE));
461 half_maxval = maxval / 2;
462 for (val = 0; val <= (INT32) maxval; val++) {
463 /* The multiplication here must be done in 32 bits to avoid overflow */
464 source->rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
465 }
466 }
467}
468
469
470/*
471 * Finish up at the end of the file.
472 */
473
474METHODDEF(void)
475finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
476{
477 /* no work */
478}
479
480
481/*
482 * The module selection routine for PPM format input.
483 */
484
486jinit_read_ppm (j_compress_ptr cinfo)
487{
488 ppm_source_ptr source;
489
490 /* Create module interface object */
491 source = (ppm_source_ptr) (*cinfo->mem->alloc_small)
492 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ppm_source_struct));
493 /* Fill in method ptrs, except get_pixel_rows which start_input sets */
494 source->pub.start_input = start_input_ppm;
495 source->pub.finish_input = finish_input_ppm;
496
497 return &source->pub;
498}
499
500#endif /* PPM_SUPPORTED */
signed int INT32
#define SIZEOF(_ar)
Definition: calc.h:97
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
__kernel_size_t size_t
Definition: linux.h:237
const GLubyte * c
Definition: glext.h:8905
GLuint GLfloat * val
Definition: glext.h:7180
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
_Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE *_File)
#define EOF
Definition: stdio.h:24
#define TRACEMS2(cinfo, lvl, code, p1, p2)
Definition: jerror.h:272
unsigned int JDIMENSION
Definition: jmorecfg.h:229
#define MAXJSAMPLE
Definition: jmorecfg.h:83
char JSAMPLE
Definition: jmorecfg.h:74
#define LOCAL(type)
Definition: jmorecfg.h:289
#define BITS_IN_JSAMPLE
Definition: jmorecfg.h:33
#define METHODDEF(type)
Definition: jmorecfg.h:287
#define GLOBAL(type)
Definition: jmorecfg.h:291
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
@ JCS_GRAYSCALE
Definition: jpeglib.h:222
@ JCS_RGB
Definition: jpeglib.h:223
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:75
#define JPOOL_IMAGE
Definition: jpeglib.h:808
#define c
Definition: ke_i.h:80
static PVOID ptr
Definition: dispmode.c:27
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
static FILE * infile
Definition: rdjpgcom.c:65
static calc_node_t temp
Definition: rpn_ieee.c:38
JDIMENSION image_height
Definition: jpeglib.h:303
J_COLOR_SPACE in_color_space
Definition: jpeglib.h:305
JDIMENSION image_width
Definition: jpeglib.h:302
Definition: general.c:220
#define ReadOK(tif, buf, size)
Definition: tiffiop.h:252