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