xref: /plan9/sys/src/cmd/gs/jpeg/rdppm.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * rdppm.c
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * Copyright (C) 1991-1997, Thomas G. Lane.
57dd7cddfSDavid du Colombier  * This file is part of the Independent JPEG Group's software.
67dd7cddfSDavid du Colombier  * For conditions of distribution and use, see the accompanying README file.
77dd7cddfSDavid du Colombier  *
87dd7cddfSDavid du Colombier  * This file contains routines to read input images in PPM/PGM format.
97dd7cddfSDavid du Colombier  * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
107dd7cddfSDavid du Colombier  * The PBMPLUS library is NOT required to compile this software
117dd7cddfSDavid du Colombier  * (but it is highly useful as a set of PPM image manipulation programs).
127dd7cddfSDavid du Colombier  *
137dd7cddfSDavid du Colombier  * These routines may need modification for non-Unix environments or
147dd7cddfSDavid du Colombier  * specialized applications.  As they stand, they assume input from
157dd7cddfSDavid du Colombier  * an ordinary stdio stream.  They further assume that reading begins
167dd7cddfSDavid du Colombier  * at the start of the file; start_input may need work if the
177dd7cddfSDavid du Colombier  * user interface has already read some data (e.g., to determine that
187dd7cddfSDavid du Colombier  * the file is indeed PPM format).
197dd7cddfSDavid du Colombier  */
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier #include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier #ifdef PPM_SUPPORTED
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier /* Portions of this code are based on the PBMPLUS library, which is:
277dd7cddfSDavid du Colombier **
287dd7cddfSDavid du Colombier ** Copyright (C) 1988 by Jef Poskanzer.
297dd7cddfSDavid du Colombier **
307dd7cddfSDavid du Colombier ** Permission to use, copy, modify, and distribute this software and its
317dd7cddfSDavid du Colombier ** documentation for any purpose and without fee is hereby granted, provided
327dd7cddfSDavid du Colombier ** that the above copyright notice appear in all copies and that both that
337dd7cddfSDavid du Colombier ** copyright notice and this permission notice appear in supporting
347dd7cddfSDavid du Colombier ** documentation.  This software is provided "as is" without express or
357dd7cddfSDavid du Colombier ** implied warranty.
367dd7cddfSDavid du Colombier */
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier /* Macros to deal with unsigned chars as efficiently as compiler allows */
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier #ifdef HAVE_UNSIGNED_CHAR
427dd7cddfSDavid du Colombier typedef unsigned char U_CHAR;
437dd7cddfSDavid du Colombier #define UCH(x)	((int) (x))
447dd7cddfSDavid du Colombier #else /* !HAVE_UNSIGNED_CHAR */
457dd7cddfSDavid du Colombier #ifdef CHAR_IS_UNSIGNED
467dd7cddfSDavid du Colombier typedef char U_CHAR;
477dd7cddfSDavid du Colombier #define UCH(x)	((int) (x))
487dd7cddfSDavid du Colombier #else
497dd7cddfSDavid du Colombier typedef char U_CHAR;
507dd7cddfSDavid du Colombier #define UCH(x)	((int) (x) & 0xFF)
517dd7cddfSDavid du Colombier #endif
527dd7cddfSDavid du Colombier #endif /* HAVE_UNSIGNED_CHAR */
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier #define	ReadOK(file,buffer,len)	(JFREAD(file,buffer,len) == ((size_t) (len)))
567dd7cddfSDavid du Colombier 
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier /*
597dd7cddfSDavid du Colombier  * On most systems, reading individual bytes with getc() is drastically less
607dd7cddfSDavid du Colombier  * efficient than buffering a row at a time with fread().  On PCs, we must
617dd7cddfSDavid du Colombier  * allocate the buffer in near data space, because we are assuming small-data
627dd7cddfSDavid du Colombier  * memory model, wherein fread() can't reach far memory.  If you need to
637dd7cddfSDavid du Colombier  * process very wide images on a PC, you might have to compile in large-memory
647dd7cddfSDavid du Colombier  * model, or else replace fread() with a getc() loop --- which will be much
657dd7cddfSDavid du Colombier  * slower.
667dd7cddfSDavid du Colombier  */
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier /* Private version of data source object */
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier typedef struct {
727dd7cddfSDavid du Colombier   struct cjpeg_source_struct pub; /* public fields */
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier   U_CHAR *iobuffer;		/* non-FAR pointer to I/O buffer */
757dd7cddfSDavid du Colombier   JSAMPROW pixrow;		/* FAR pointer to same */
767dd7cddfSDavid du Colombier   size_t buffer_width;		/* width of I/O buffer */
777dd7cddfSDavid du Colombier   JSAMPLE *rescale;		/* => maxval-remapping array, or NULL */
787dd7cddfSDavid du Colombier } ppm_source_struct;
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier typedef ppm_source_struct * ppm_source_ptr;
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier LOCAL(int)
pbm_getc(FILE * infile)847dd7cddfSDavid du Colombier pbm_getc (FILE * infile)
857dd7cddfSDavid du Colombier /* Read next char, skipping over any comments */
867dd7cddfSDavid du Colombier /* A comment/newline sequence is returned as a newline */
877dd7cddfSDavid du Colombier {
887dd7cddfSDavid du Colombier   register int ch;
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier   ch = getc(infile);
917dd7cddfSDavid du Colombier   if (ch == '#') {
927dd7cddfSDavid du Colombier     do {
937dd7cddfSDavid du Colombier       ch = getc(infile);
947dd7cddfSDavid du Colombier     } while (ch != '\n' && ch != EOF);
957dd7cddfSDavid du Colombier   }
967dd7cddfSDavid du Colombier   return ch;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier LOCAL(unsigned int)
read_pbm_integer(j_compress_ptr cinfo,FILE * infile)1017dd7cddfSDavid du Colombier read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
1027dd7cddfSDavid du Colombier /* Read an unsigned decimal integer from the PPM file */
1037dd7cddfSDavid du Colombier /* Swallows one trailing character after the integer */
1047dd7cddfSDavid du Colombier /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
1057dd7cddfSDavid du Colombier /* This should not be a problem in practice. */
1067dd7cddfSDavid du Colombier {
1077dd7cddfSDavid du Colombier   register int ch;
1087dd7cddfSDavid du Colombier   register unsigned int val;
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier   /* Skip any leading whitespace */
1117dd7cddfSDavid du Colombier   do {
1127dd7cddfSDavid du Colombier     ch = pbm_getc(infile);
1137dd7cddfSDavid du Colombier     if (ch == EOF)
1147dd7cddfSDavid du Colombier       ERREXIT(cinfo, JERR_INPUT_EOF);
1157dd7cddfSDavid du Colombier   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier   if (ch < '0' || ch > '9')
1187dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier   val = ch - '0';
1217dd7cddfSDavid du Colombier   while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
1227dd7cddfSDavid du Colombier     val *= 10;
1237dd7cddfSDavid du Colombier     val += ch - '0';
1247dd7cddfSDavid du Colombier   }
1257dd7cddfSDavid du Colombier   return val;
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier /*
1307dd7cddfSDavid du Colombier  * Read one row of pixels.
1317dd7cddfSDavid du Colombier  *
1327dd7cddfSDavid du Colombier  * We provide several different versions depending on input file format.
1337dd7cddfSDavid du Colombier  * In all cases, input is scaled to the size of JSAMPLE.
1347dd7cddfSDavid du Colombier  *
1357dd7cddfSDavid du Colombier  * A really fast path is provided for reading byte/sample raw files with
1367dd7cddfSDavid du Colombier  * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
1377dd7cddfSDavid du Colombier  */
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_text_gray_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)1417dd7cddfSDavid du Colombier get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
1427dd7cddfSDavid du Colombier /* This version is for reading text-format PGM files with any maxval */
1437dd7cddfSDavid du Colombier {
1447dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
1457dd7cddfSDavid du Colombier   FILE * infile = source->pub.input_file;
1467dd7cddfSDavid du Colombier   register JSAMPROW ptr;
1477dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
1487dd7cddfSDavid du Colombier   JDIMENSION col;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
1517dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
1527dd7cddfSDavid du Colombier     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
1537dd7cddfSDavid du Colombier   }
1547dd7cddfSDavid du Colombier   return 1;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_text_rgb_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)1597dd7cddfSDavid du Colombier get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
1607dd7cddfSDavid du Colombier /* This version is for reading text-format PPM files with any maxval */
1617dd7cddfSDavid du Colombier {
1627dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
1637dd7cddfSDavid du Colombier   FILE * infile = source->pub.input_file;
1647dd7cddfSDavid du Colombier   register JSAMPROW ptr;
1657dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
1667dd7cddfSDavid du Colombier   JDIMENSION col;
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
1697dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
1707dd7cddfSDavid du Colombier     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
1717dd7cddfSDavid du Colombier     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
1727dd7cddfSDavid du Colombier     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
1737dd7cddfSDavid du Colombier   }
1747dd7cddfSDavid du Colombier   return 1;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_scaled_gray_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)1797dd7cddfSDavid du Colombier get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
1807dd7cddfSDavid du Colombier /* This version is for reading raw-byte-format PGM files with any maxval */
1817dd7cddfSDavid du Colombier {
1827dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
1837dd7cddfSDavid du Colombier   register JSAMPROW ptr;
1847dd7cddfSDavid du Colombier   register U_CHAR * bufferptr;
1857dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
1867dd7cddfSDavid du Colombier   JDIMENSION col;
1877dd7cddfSDavid du Colombier 
1887dd7cddfSDavid du Colombier   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
1897dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_INPUT_EOF);
1907dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
1917dd7cddfSDavid du Colombier   bufferptr = source->iobuffer;
1927dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
1937dd7cddfSDavid du Colombier     *ptr++ = rescale[UCH(*bufferptr++)];
1947dd7cddfSDavid du Colombier   }
1957dd7cddfSDavid du Colombier   return 1;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_scaled_rgb_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)2007dd7cddfSDavid du Colombier get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
2017dd7cddfSDavid du Colombier /* This version is for reading raw-byte-format PPM files with any maxval */
2027dd7cddfSDavid du Colombier {
2037dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
2047dd7cddfSDavid du Colombier   register JSAMPROW ptr;
2057dd7cddfSDavid du Colombier   register U_CHAR * bufferptr;
2067dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
2077dd7cddfSDavid du Colombier   JDIMENSION col;
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
2107dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_INPUT_EOF);
2117dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
2127dd7cddfSDavid du Colombier   bufferptr = source->iobuffer;
2137dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
2147dd7cddfSDavid du Colombier     *ptr++ = rescale[UCH(*bufferptr++)];
2157dd7cddfSDavid du Colombier     *ptr++ = rescale[UCH(*bufferptr++)];
2167dd7cddfSDavid du Colombier     *ptr++ = rescale[UCH(*bufferptr++)];
2177dd7cddfSDavid du Colombier   }
2187dd7cddfSDavid du Colombier   return 1;
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_raw_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)2237dd7cddfSDavid du Colombier get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
2247dd7cddfSDavid du Colombier /* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
2257dd7cddfSDavid du Colombier  * In this case we just read right into the JSAMPLE buffer!
2267dd7cddfSDavid du Colombier  * Note that same code works for PPM and PGM files.
2277dd7cddfSDavid du Colombier  */
2287dd7cddfSDavid du Colombier {
2297dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
2327dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_INPUT_EOF);
2337dd7cddfSDavid du Colombier   return 1;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_word_gray_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)2387dd7cddfSDavid du Colombier get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
2397dd7cddfSDavid du Colombier /* This version is for reading raw-word-format PGM files with any maxval */
2407dd7cddfSDavid du Colombier {
2417dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
2427dd7cddfSDavid du Colombier   register JSAMPROW ptr;
2437dd7cddfSDavid du Colombier   register U_CHAR * bufferptr;
2447dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
2457dd7cddfSDavid du Colombier   JDIMENSION col;
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
2487dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_INPUT_EOF);
2497dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
2507dd7cddfSDavid du Colombier   bufferptr = source->iobuffer;
2517dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
2527dd7cddfSDavid du Colombier     register int temp;
2537dd7cddfSDavid du Colombier     temp  = UCH(*bufferptr++);
2547dd7cddfSDavid du Colombier     temp |= UCH(*bufferptr++) << 8;
2557dd7cddfSDavid du Colombier     *ptr++ = rescale[temp];
2567dd7cddfSDavid du Colombier   }
2577dd7cddfSDavid du Colombier   return 1;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier 
2617dd7cddfSDavid du Colombier METHODDEF(JDIMENSION)
get_word_rgb_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)2627dd7cddfSDavid du Colombier get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
2637dd7cddfSDavid du Colombier /* This version is for reading raw-word-format PPM files with any maxval */
2647dd7cddfSDavid du Colombier {
2657dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
2667dd7cddfSDavid du Colombier   register JSAMPROW ptr;
2677dd7cddfSDavid du Colombier   register U_CHAR * bufferptr;
2687dd7cddfSDavid du Colombier   register JSAMPLE *rescale = source->rescale;
2697dd7cddfSDavid du Colombier   JDIMENSION col;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
2727dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_INPUT_EOF);
2737dd7cddfSDavid du Colombier   ptr = source->pub.buffer[0];
2747dd7cddfSDavid du Colombier   bufferptr = source->iobuffer;
2757dd7cddfSDavid du Colombier   for (col = cinfo->image_width; col > 0; col--) {
2767dd7cddfSDavid du Colombier     register int temp;
2777dd7cddfSDavid du Colombier     temp  = UCH(*bufferptr++);
2787dd7cddfSDavid du Colombier     temp |= UCH(*bufferptr++) << 8;
2797dd7cddfSDavid du Colombier     *ptr++ = rescale[temp];
2807dd7cddfSDavid du Colombier     temp  = UCH(*bufferptr++);
2817dd7cddfSDavid du Colombier     temp |= UCH(*bufferptr++) << 8;
2827dd7cddfSDavid du Colombier     *ptr++ = rescale[temp];
2837dd7cddfSDavid du Colombier     temp  = UCH(*bufferptr++);
2847dd7cddfSDavid du Colombier     temp |= UCH(*bufferptr++) << 8;
2857dd7cddfSDavid du Colombier     *ptr++ = rescale[temp];
2867dd7cddfSDavid du Colombier   }
2877dd7cddfSDavid du Colombier   return 1;
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier 
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier /*
2927dd7cddfSDavid du Colombier  * Read the file header; return image size and component count.
2937dd7cddfSDavid du Colombier  */
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier METHODDEF(void)
start_input_ppm(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)2967dd7cddfSDavid du Colombier start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
2977dd7cddfSDavid du Colombier {
2987dd7cddfSDavid du Colombier   ppm_source_ptr source = (ppm_source_ptr) sinfo;
2997dd7cddfSDavid du Colombier   int c;
3007dd7cddfSDavid du Colombier   unsigned int w, h, maxval;
3017dd7cddfSDavid du Colombier   boolean need_iobuffer, use_raw_buffer, need_rescale;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier   if (getc(source->pub.input_file) != 'P')
3047dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_PPM_NOT);
3057dd7cddfSDavid du Colombier 
306*593dc095SDavid du Colombier   c = getc(source->pub.input_file); /* subformat discriminator character */
307*593dc095SDavid du Colombier 
308*593dc095SDavid du Colombier   /* detect unsupported variants (ie, PBM) before trying to read header */
309*593dc095SDavid du Colombier   switch (c) {
310*593dc095SDavid du Colombier   case '2':			/* it's a text-format PGM file */
311*593dc095SDavid du Colombier   case '3':			/* it's a text-format PPM file */
312*593dc095SDavid du Colombier   case '5':			/* it's a raw-format PGM file */
313*593dc095SDavid du Colombier   case '6':			/* it's a raw-format PPM file */
314*593dc095SDavid du Colombier     break;
315*593dc095SDavid du Colombier   default:
316*593dc095SDavid du Colombier     ERREXIT(cinfo, JERR_PPM_NOT);
317*593dc095SDavid du Colombier     break;
318*593dc095SDavid du Colombier   }
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier   /* fetch the remaining header info */
3217dd7cddfSDavid du Colombier   w = read_pbm_integer(cinfo, source->pub.input_file);
3227dd7cddfSDavid du Colombier   h = read_pbm_integer(cinfo, source->pub.input_file);
3237dd7cddfSDavid du Colombier   maxval = read_pbm_integer(cinfo, source->pub.input_file);
3247dd7cddfSDavid du Colombier 
3257dd7cddfSDavid du Colombier   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
3267dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_PPM_NOT);
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier   cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
3297dd7cddfSDavid du Colombier   cinfo->image_width = (JDIMENSION) w;
3307dd7cddfSDavid du Colombier   cinfo->image_height = (JDIMENSION) h;
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier   /* initialize flags to most common settings */
3337dd7cddfSDavid du Colombier   need_iobuffer = TRUE;		/* do we need an I/O buffer? */
3347dd7cddfSDavid du Colombier   use_raw_buffer = FALSE;	/* do we map input buffer onto I/O buffer? */
3357dd7cddfSDavid du Colombier   need_rescale = TRUE;		/* do we need a rescale array? */
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier   switch (c) {
3387dd7cddfSDavid du Colombier   case '2':			/* it's a text-format PGM file */
3397dd7cddfSDavid du Colombier     cinfo->input_components = 1;
3407dd7cddfSDavid du Colombier     cinfo->in_color_space = JCS_GRAYSCALE;
3417dd7cddfSDavid du Colombier     TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
3427dd7cddfSDavid du Colombier     source->pub.get_pixel_rows = get_text_gray_row;
3437dd7cddfSDavid du Colombier     need_iobuffer = FALSE;
3447dd7cddfSDavid du Colombier     break;
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier   case '3':			/* it's a text-format PPM file */
3477dd7cddfSDavid du Colombier     cinfo->input_components = 3;
3487dd7cddfSDavid du Colombier     cinfo->in_color_space = JCS_RGB;
3497dd7cddfSDavid du Colombier     TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
3507dd7cddfSDavid du Colombier     source->pub.get_pixel_rows = get_text_rgb_row;
3517dd7cddfSDavid du Colombier     need_iobuffer = FALSE;
3527dd7cddfSDavid du Colombier     break;
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier   case '5':			/* it's a raw-format PGM file */
3557dd7cddfSDavid du Colombier     cinfo->input_components = 1;
3567dd7cddfSDavid du Colombier     cinfo->in_color_space = JCS_GRAYSCALE;
3577dd7cddfSDavid du Colombier     TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
3587dd7cddfSDavid du Colombier     if (maxval > 255) {
3597dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_word_gray_row;
3607dd7cddfSDavid du Colombier     } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
3617dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_raw_row;
3627dd7cddfSDavid du Colombier       use_raw_buffer = TRUE;
3637dd7cddfSDavid du Colombier       need_rescale = FALSE;
3647dd7cddfSDavid du Colombier     } else {
3657dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_scaled_gray_row;
3667dd7cddfSDavid du Colombier     }
3677dd7cddfSDavid du Colombier     break;
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier   case '6':			/* it's a raw-format PPM file */
3707dd7cddfSDavid du Colombier     cinfo->input_components = 3;
3717dd7cddfSDavid du Colombier     cinfo->in_color_space = JCS_RGB;
3727dd7cddfSDavid du Colombier     TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
3737dd7cddfSDavid du Colombier     if (maxval > 255) {
3747dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_word_rgb_row;
3757dd7cddfSDavid du Colombier     } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
3767dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_raw_row;
3777dd7cddfSDavid du Colombier       use_raw_buffer = TRUE;
3787dd7cddfSDavid du Colombier       need_rescale = FALSE;
3797dd7cddfSDavid du Colombier     } else {
3807dd7cddfSDavid du Colombier       source->pub.get_pixel_rows = get_scaled_rgb_row;
3817dd7cddfSDavid du Colombier     }
3827dd7cddfSDavid du Colombier     break;
3837dd7cddfSDavid du Colombier   }
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier   /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
3867dd7cddfSDavid du Colombier   if (need_iobuffer) {
3877dd7cddfSDavid du Colombier     source->buffer_width = (size_t) w * cinfo->input_components *
3887dd7cddfSDavid du Colombier       ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR)));
3897dd7cddfSDavid du Colombier     source->iobuffer = (U_CHAR *)
3907dd7cddfSDavid du Colombier       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
3917dd7cddfSDavid du Colombier 				  source->buffer_width);
3927dd7cddfSDavid du Colombier   }
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier   /* Create compressor input buffer. */
3957dd7cddfSDavid du Colombier   if (use_raw_buffer) {
3967dd7cddfSDavid du Colombier     /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
3977dd7cddfSDavid du Colombier     /* Synthesize a JSAMPARRAY pointer structure */
3987dd7cddfSDavid du Colombier     /* Cast here implies near->far pointer conversion on PCs */
3997dd7cddfSDavid du Colombier     source->pixrow = (JSAMPROW) source->iobuffer;
4007dd7cddfSDavid du Colombier     source->pub.buffer = & source->pixrow;
4017dd7cddfSDavid du Colombier     source->pub.buffer_height = 1;
4027dd7cddfSDavid du Colombier   } else {
4037dd7cddfSDavid du Colombier     /* Need to translate anyway, so make a separate sample buffer. */
4047dd7cddfSDavid du Colombier     source->pub.buffer = (*cinfo->mem->alloc_sarray)
4057dd7cddfSDavid du Colombier       ((j_common_ptr) cinfo, JPOOL_IMAGE,
4067dd7cddfSDavid du Colombier        (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1);
4077dd7cddfSDavid du Colombier     source->pub.buffer_height = 1;
4087dd7cddfSDavid du Colombier   }
4097dd7cddfSDavid du Colombier 
4107dd7cddfSDavid du Colombier   /* Compute the rescaling array if required. */
4117dd7cddfSDavid du Colombier   if (need_rescale) {
4127dd7cddfSDavid du Colombier     INT32 val, half_maxval;
4137dd7cddfSDavid du Colombier 
4147dd7cddfSDavid du Colombier     /* On 16-bit-int machines we have to be careful of maxval = 65535 */
4157dd7cddfSDavid du Colombier     source->rescale = (JSAMPLE *)
4167dd7cddfSDavid du Colombier       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4177dd7cddfSDavid du Colombier 				  (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
4187dd7cddfSDavid du Colombier     half_maxval = maxval / 2;
4197dd7cddfSDavid du Colombier     for (val = 0; val <= (INT32) maxval; val++) {
4207dd7cddfSDavid du Colombier       /* The multiplication here must be done in 32 bits to avoid overflow */
4217dd7cddfSDavid du Colombier       source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
4227dd7cddfSDavid du Colombier     }
4237dd7cddfSDavid du Colombier   }
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier 
4267dd7cddfSDavid du Colombier 
4277dd7cddfSDavid du Colombier /*
4287dd7cddfSDavid du Colombier  * Finish up at the end of the file.
4297dd7cddfSDavid du Colombier  */
4307dd7cddfSDavid du Colombier 
4317dd7cddfSDavid du Colombier METHODDEF(void)
finish_input_ppm(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)4327dd7cddfSDavid du Colombier finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier   /* no work */
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier 
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier /*
4397dd7cddfSDavid du Colombier  * The module selection routine for PPM format input.
4407dd7cddfSDavid du Colombier  */
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier GLOBAL(cjpeg_source_ptr)
jinit_read_ppm(j_compress_ptr cinfo)4437dd7cddfSDavid du Colombier jinit_read_ppm (j_compress_ptr cinfo)
4447dd7cddfSDavid du Colombier {
4457dd7cddfSDavid du Colombier   ppm_source_ptr source;
4467dd7cddfSDavid du Colombier 
4477dd7cddfSDavid du Colombier   /* Create module interface object */
4487dd7cddfSDavid du Colombier   source = (ppm_source_ptr)
4497dd7cddfSDavid du Colombier       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4507dd7cddfSDavid du Colombier 				  SIZEOF(ppm_source_struct));
4517dd7cddfSDavid du Colombier   /* Fill in method ptrs, except get_pixel_rows which start_input sets */
4527dd7cddfSDavid du Colombier   source->pub.start_input = start_input_ppm;
4537dd7cddfSDavid du Colombier   source->pub.finish_input = finish_input_ppm;
4547dd7cddfSDavid du Colombier 
4557dd7cddfSDavid du Colombier   return (cjpeg_source_ptr) source;
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier 
4587dd7cddfSDavid du Colombier #endif /* PPM_SUPPORTED */
459