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