Final 350 project

Dependencies:   uzair Camera_LS_Y201 F7_Ethernet LCD_DISCO_F746NG NetworkAPI SDFileSystem mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rdppm.c Source File

rdppm.c

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 */