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