ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rdppm.c
Go to the documentation of this file.
00001 /*
00002  * rdppm.c
00003  *
00004  * Copyright (C) 1991-1997, Thomas G. Lane.
00005  * Modified 2009 by Bill Allombert, Guido Vollbeding.
00006  * This file is part of the Independent JPEG Group's software.
00007  * For conditions of distribution and use, see the accompanying README file.
00008  *
00009  * This file contains routines to read input images in PPM/PGM format.
00010  * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
00011  * The PBMPLUS library is NOT required to compile this software
00012  * (but it is highly useful as a set of PPM image manipulation programs).
00013  *
00014  * These routines may need modification for non-Unix environments or
00015  * specialized applications.  As they stand, they assume input from
00016  * an ordinary stdio stream.  They further assume that reading begins
00017  * at the start of the file; start_input may need work if the
00018  * user interface has already read some data (e.g., to determine that
00019  * the file is indeed PPM format).
00020  */
00021 
00022 #include "cdjpeg.h"     /* Common decls for cjpeg/djpeg applications */
00023 
00024 #ifdef PPM_SUPPORTED
00025 
00026 
00027 /* Portions of this code are based on the PBMPLUS library, which is:
00028 **
00029 ** Copyright (C) 1988 by Jef Poskanzer.
00030 **
00031 ** Permission to use, copy, modify, and distribute this software and its
00032 ** documentation for any purpose and without fee is hereby granted, provided
00033 ** that the above copyright notice appear in all copies and that both that
00034 ** copyright notice and this permission notice appear in supporting
00035 ** documentation.  This software is provided "as is" without express or
00036 ** implied warranty.
00037 */
00038 
00039 
00040 /* Macros to deal with unsigned chars as efficiently as compiler allows */
00041 
00042 #ifdef HAVE_UNSIGNED_CHAR
00043 typedef unsigned char U_CHAR;
00044 #define UCH(x)  ((int) (x))
00045 #else /* !HAVE_UNSIGNED_CHAR */
00046 #ifdef CHAR_IS_UNSIGNED
00047 typedef char U_CHAR;
00048 #define UCH(x)  ((int) (x))
00049 #else
00050 typedef char U_CHAR;
00051 #define UCH(x)  ((int) (x) & 0xFF)
00052 #endif
00053 #endif /* HAVE_UNSIGNED_CHAR */
00054 
00055 
00056 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
00057 
00058 
00059 /*
00060  * On most systems, reading individual bytes with getc() is drastically less
00061  * efficient than buffering a row at a time with fread().  On PCs, we must
00062  * allocate the buffer in near data space, because we are assuming small-data
00063  * memory model, wherein fread() can't reach far memory.  If you need to
00064  * process very wide images on a PC, you might have to compile in large-memory
00065  * model, or else replace fread() with a getc() loop --- which will be much
00066  * slower.
00067  */
00068 
00069 
00070 /* Private version of data source object */
00071 
00072 typedef struct {
00073   struct cjpeg_source_struct pub; /* public fields */
00074 
00075   U_CHAR *iobuffer;     /* non-FAR pointer to I/O buffer */
00076   JSAMPROW pixrow;      /* FAR pointer to same */
00077   size_t buffer_width;      /* width of I/O buffer */
00078   JSAMPLE *rescale;     /* => maxval-remapping array, or NULL */
00079 } ppm_source_struct;
00080 
00081 typedef ppm_source_struct * ppm_source_ptr;
00082 
00083 
00084 LOCAL(int)
00085 pbm_getc (FILE * infile)
00086 /* Read next char, skipping over any comments */
00087 /* A comment/newline sequence is returned as a newline */
00088 {
00089   register int ch;
00090 
00091   ch = getc(infile);
00092   if (ch == '#') {
00093     do {
00094       ch = getc(infile);
00095     } while (ch != '\n' && ch != EOF);
00096   }
00097   return ch;
00098 }
00099 
00100 
00101 LOCAL(unsigned int)
00102 read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
00103 /* Read an unsigned decimal integer from the PPM file */
00104 /* Swallows one trailing character after the integer */
00105 /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
00106 /* This should not be a problem in practice. */
00107 {
00108   register int ch;
00109   register unsigned int val;
00110 
00111   /* Skip any leading whitespace */
00112   do {
00113     ch = pbm_getc(infile);
00114     if (ch == EOF)
00115       ERREXIT(cinfo, JERR_INPUT_EOF);
00116   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
00117 
00118   if (ch < '0' || ch > '9')
00119     ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
00120 
00121   val = ch - '0';
00122   while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
00123     val *= 10;
00124     val += ch - '0';
00125   }
00126   return val;
00127 }
00128 
00129 
00130 /*
00131  * Read one row of pixels.
00132  *
00133  * We provide several different versions depending on input file format.
00134  * In all cases, input is scaled to the size of JSAMPLE.
00135  *
00136  * A really fast path is provided for reading byte/sample raw files with
00137  * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
00138  */
00139 
00140 
00141 METHODDEF(JDIMENSION)
00142 get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00143 /* This version is for reading text-format PGM files with any maxval */
00144 {
00145   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00146   FILE * infile = source->pub.input_file;
00147   register JSAMPROW ptr;
00148   register JSAMPLE *rescale = source->rescale;
00149   JDIMENSION col;
00150 
00151   ptr = source->pub.buffer[0];
00152   for (col = cinfo->image_width; col > 0; col--) {
00153     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
00154   }
00155   return 1;
00156 }
00157 
00158 
00159 METHODDEF(JDIMENSION)
00160 get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00161 /* This version is for reading text-format PPM files with any maxval */
00162 {
00163   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00164   FILE * infile = source->pub.input_file;
00165   register JSAMPROW ptr;
00166   register JSAMPLE *rescale = source->rescale;
00167   JDIMENSION col;
00168 
00169   ptr = source->pub.buffer[0];
00170   for (col = cinfo->image_width; col > 0; col--) {
00171     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
00172     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
00173     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
00174   }
00175   return 1;
00176 }
00177 
00178 
00179 METHODDEF(JDIMENSION)
00180 get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00181 /* This version is for reading raw-byte-format PGM files with any maxval */
00182 {
00183   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00184   register JSAMPROW ptr;
00185   register U_CHAR * bufferptr;
00186   register JSAMPLE *rescale = source->rescale;
00187   JDIMENSION col;
00188 
00189   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
00190     ERREXIT(cinfo, JERR_INPUT_EOF);
00191   ptr = source->pub.buffer[0];
00192   bufferptr = source->iobuffer;
00193   for (col = cinfo->image_width; col > 0; col--) {
00194     *ptr++ = rescale[UCH(*bufferptr++)];
00195   }
00196   return 1;
00197 }
00198 
00199 
00200 METHODDEF(JDIMENSION)
00201 get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00202 /* This version is for reading raw-byte-format PPM files with any maxval */
00203 {
00204   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00205   register JSAMPROW ptr;
00206   register U_CHAR * bufferptr;
00207   register JSAMPLE *rescale = source->rescale;
00208   JDIMENSION col;
00209 
00210   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
00211     ERREXIT(cinfo, JERR_INPUT_EOF);
00212   ptr = source->pub.buffer[0];
00213   bufferptr = source->iobuffer;
00214   for (col = cinfo->image_width; col > 0; col--) {
00215     *ptr++ = rescale[UCH(*bufferptr++)];
00216     *ptr++ = rescale[UCH(*bufferptr++)];
00217     *ptr++ = rescale[UCH(*bufferptr++)];
00218   }
00219   return 1;
00220 }
00221 
00222 
00223 METHODDEF(JDIMENSION)
00224 get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00225 /* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
00226  * In this case we just read right into the JSAMPLE buffer!
00227  * Note that same code works for PPM and PGM files.
00228  */
00229 {
00230   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00231 
00232   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
00233     ERREXIT(cinfo, JERR_INPUT_EOF);
00234   return 1;
00235 }
00236 
00237 
00238 METHODDEF(JDIMENSION)
00239 get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00240 /* This version is for reading raw-word-format PGM files with any maxval */
00241 {
00242   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00243   register JSAMPROW ptr;
00244   register U_CHAR * bufferptr;
00245   register JSAMPLE *rescale = source->rescale;
00246   JDIMENSION col;
00247 
00248   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
00249     ERREXIT(cinfo, JERR_INPUT_EOF);
00250   ptr = source->pub.buffer[0];
00251   bufferptr = source->iobuffer;
00252   for (col = cinfo->image_width; col > 0; col--) {
00253     register int temp;
00254     temp  = UCH(*bufferptr++) << 8;
00255     temp |= UCH(*bufferptr++);
00256     *ptr++ = rescale[temp];
00257   }
00258   return 1;
00259 }
00260 
00261 
00262 METHODDEF(JDIMENSION)
00263 get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00264 /* This version is for reading raw-word-format PPM files with any maxval */
00265 {
00266   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00267   register JSAMPROW ptr;
00268   register U_CHAR * bufferptr;
00269   register JSAMPLE *rescale = source->rescale;
00270   JDIMENSION col;
00271 
00272   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
00273     ERREXIT(cinfo, JERR_INPUT_EOF);
00274   ptr = source->pub.buffer[0];
00275   bufferptr = source->iobuffer;
00276   for (col = cinfo->image_width; col > 0; col--) {
00277     register int temp;
00278     temp  = UCH(*bufferptr++) << 8;
00279     temp |= UCH(*bufferptr++);
00280     *ptr++ = rescale[temp];
00281     temp  = UCH(*bufferptr++) << 8;
00282     temp |= UCH(*bufferptr++);
00283     *ptr++ = rescale[temp];
00284     temp  = UCH(*bufferptr++) << 8;
00285     temp |= UCH(*bufferptr++);
00286     *ptr++ = rescale[temp];
00287   }
00288   return 1;
00289 }
00290 
00291 
00292 /*
00293  * Read the file header; return image size and component count.
00294  */
00295 
00296 METHODDEF(void)
00297 start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00298 {
00299   ppm_source_ptr source = (ppm_source_ptr) sinfo;
00300   int c;
00301   unsigned int w, h, maxval;
00302   boolean need_iobuffer, use_raw_buffer, need_rescale;
00303 
00304   if (getc(source->pub.input_file) != 'P')
00305     ERREXIT(cinfo, JERR_PPM_NOT);
00306 
00307   c = getc(source->pub.input_file); /* subformat discriminator character */
00308 
00309   /* detect unsupported variants (ie, PBM) before trying to read header */
00310   switch (c) {
00311   case '2':         /* it's a text-format PGM file */
00312   case '3':         /* it's a text-format PPM file */
00313   case '5':         /* it's a raw-format PGM file */
00314   case '6':         /* it's a raw-format PPM file */
00315     break;
00316   default:
00317     ERREXIT(cinfo, JERR_PPM_NOT);
00318     break;
00319   }
00320 
00321   /* fetch the remaining header info */
00322   w = read_pbm_integer(cinfo, source->pub.input_file);
00323   h = read_pbm_integer(cinfo, source->pub.input_file);
00324   maxval = read_pbm_integer(cinfo, source->pub.input_file);
00325 
00326   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
00327     ERREXIT(cinfo, JERR_PPM_NOT);
00328 
00329   cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
00330   cinfo->image_width = (JDIMENSION) w;
00331   cinfo->image_height = (JDIMENSION) h;
00332 
00333   /* initialize flags to most common settings */
00334   need_iobuffer = TRUE;     /* do we need an I/O buffer? */
00335   use_raw_buffer = FALSE;   /* do we map input buffer onto I/O buffer? */
00336   need_rescale = TRUE;      /* do we need a rescale array? */
00337 
00338   switch (c) {
00339   case '2':         /* it's a text-format PGM file */
00340     cinfo->input_components = 1;
00341     cinfo->in_color_space = JCS_GRAYSCALE;
00342     TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
00343     source->pub.get_pixel_rows = get_text_gray_row;
00344     need_iobuffer = FALSE;
00345     break;
00346 
00347   case '3':         /* it's a text-format PPM file */
00348     cinfo->input_components = 3;
00349     cinfo->in_color_space = JCS_RGB;
00350     TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
00351     source->pub.get_pixel_rows = get_text_rgb_row;
00352     need_iobuffer = FALSE;
00353     break;
00354 
00355   case '5':         /* it's a raw-format PGM file */
00356     cinfo->input_components = 1;
00357     cinfo->in_color_space = JCS_GRAYSCALE;
00358     TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
00359     if (maxval > 255) {
00360       source->pub.get_pixel_rows = get_word_gray_row;
00361     } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
00362       source->pub.get_pixel_rows = get_raw_row;
00363       use_raw_buffer = TRUE;
00364       need_rescale = FALSE;
00365     } else {
00366       source->pub.get_pixel_rows = get_scaled_gray_row;
00367     }
00368     break;
00369 
00370   case '6':         /* it's a raw-format PPM file */
00371     cinfo->input_components = 3;
00372     cinfo->in_color_space = JCS_RGB;
00373     TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
00374     if (maxval > 255) {
00375       source->pub.get_pixel_rows = get_word_rgb_row;
00376     } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
00377       source->pub.get_pixel_rows = get_raw_row;
00378       use_raw_buffer = TRUE;
00379       need_rescale = FALSE;
00380     } else {
00381       source->pub.get_pixel_rows = get_scaled_rgb_row;
00382     }
00383     break;
00384   }
00385 
00386   /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
00387   if (need_iobuffer) {
00388     source->buffer_width = (size_t) w * cinfo->input_components *
00389       ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR)));
00390     source->iobuffer = (U_CHAR *)
00391       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00392                   source->buffer_width);
00393   }
00394 
00395   /* Create compressor input buffer. */
00396   if (use_raw_buffer) {
00397     /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
00398     /* Synthesize a JSAMPARRAY pointer structure */
00399     /* Cast here implies near->far pointer conversion on PCs */
00400     source->pixrow = (JSAMPROW) source->iobuffer;
00401     source->pub.buffer = & source->pixrow;
00402     source->pub.buffer_height = 1;
00403   } else {
00404     /* Need to translate anyway, so make a separate sample buffer. */
00405     source->pub.buffer = (*cinfo->mem->alloc_sarray)
00406       ((j_common_ptr) cinfo, JPOOL_IMAGE,
00407        (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1);
00408     source->pub.buffer_height = 1;
00409   }
00410 
00411   /* Compute the rescaling array if required. */
00412   if (need_rescale) {
00413     INT32 val, half_maxval;
00414 
00415     /* On 16-bit-int machines we have to be careful of maxval = 65535 */
00416     source->rescale = (JSAMPLE *)
00417       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00418                   (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
00419     half_maxval = maxval / 2;
00420     for (val = 0; val <= (INT32) maxval; val++) {
00421       /* The multiplication here must be done in 32 bits to avoid overflow */
00422       source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
00423     }
00424   }
00425 }
00426 
00427 
00428 /*
00429  * Finish up at the end of the file.
00430  */
00431 
00432 METHODDEF(void)
00433 finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00434 {
00435   /* no work */
00436 }
00437 
00438 
00439 /*
00440  * The module selection routine for PPM format input.
00441  */
00442 
00443 GLOBAL(cjpeg_source_ptr)
00444 jinit_read_ppm (j_compress_ptr cinfo)
00445 {
00446   ppm_source_ptr source;
00447 
00448   /* Create module interface object */
00449   source = (ppm_source_ptr)
00450       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00451                   SIZEOF(ppm_source_struct));
00452   /* Fill in method ptrs, except get_pixel_rows which start_input sets */
00453   source->pub.start_input = start_input_ppm;
00454   source->pub.finish_input = finish_input_ppm;
00455 
00456   return (cjpeg_source_ptr) source;
00457 }
00458 
00459 #endif /* PPM_SUPPORTED */

Generated on Sat May 26 2012 04:18:14 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.