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