home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / jpeg / part22 / rdppm.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  12KB  |  385 lines

  1. /*
  2.  * rdppm.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in PPM/PGM format.
  9.  * The PBMPLUS library is NOT required to compile this software
  10.  * (but it is highly useful as a set of PPM image manipulation programs).
  11.  *
  12.  * These routines may need modification for non-Unix environments or
  13.  * specialized applications.  As they stand, they assume input from
  14.  * an ordinary stdio stream.  They further assume that reading begins
  15.  * at the start of the file; start_input may need work if the
  16.  * user interface has already read some data (e.g., to determine that
  17.  * the file is indeed PPM format).
  18.  */
  19.  
  20. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  21.  
  22. #ifdef PPM_SUPPORTED
  23.  
  24.  
  25. /* Portions of this code are based on the PBMPLUS library, which is:
  26. **
  27. ** Copyright (C) 1988 by Jef Poskanzer.
  28. **
  29. ** Permission to use, copy, modify, and distribute this software and its
  30. ** documentation for any purpose and without fee is hereby granted, provided
  31. ** that the above copyright notice appear in all copies and that both that
  32. ** copyright notice and this permission notice appear in supporting
  33. ** documentation.  This software is provided "as is" without express or
  34. ** implied warranty.
  35. */
  36.  
  37.  
  38. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  39.  
  40. #ifdef HAVE_UNSIGNED_CHAR
  41. typedef unsigned char U_CHAR;
  42. #define UCH(x)    ((int) (x))
  43. #else /* !HAVE_UNSIGNED_CHAR */
  44. #ifdef CHAR_IS_UNSIGNED
  45. typedef char U_CHAR;
  46. #define UCH(x)    ((int) (x))
  47. #else
  48. typedef char U_CHAR;
  49. #define UCH(x)    ((int) (x) & 0xFF)
  50. #endif
  51. #endif /* HAVE_UNSIGNED_CHAR */
  52.  
  53.  
  54. #define    ReadOK(file,buffer,len)    (JFREAD(file,buffer,len) == ((size_t) (len)))
  55.  
  56.  
  57. /*
  58.  * On most systems, reading individual bytes with getc() is drastically less
  59.  * efficient than buffering a row at a time with fread().  On PCs, we must
  60.  * allocate the buffer in near data space, because we are assuming small-data
  61.  * memory model, wherein fread() can't reach far memory.  If you need to
  62.  * process very wide images on a PC, you might have to compile in large-memory
  63.  * model, or else replace fread() with a getc() loop --- which will be much
  64.  * slower.
  65.  */
  66.  
  67.  
  68. /* Private version of data source object */
  69.  
  70. typedef struct {
  71.   struct cjpeg_source_struct pub; /* public fields */
  72.  
  73.   U_CHAR *iobuffer;        /* non-FAR pointer to I/O buffer */
  74.   JSAMPROW pixrow;        /* FAR pointer to same */
  75.   JDIMENSION buffer_width;    /* width of one row */
  76.   JSAMPLE *rescale;        /* => maxval-remapping array, or NULL */
  77. } ppm_source_struct;
  78.  
  79. typedef ppm_source_struct * ppm_source_ptr;
  80.  
  81.  
  82. LOCAL int
  83. pbm_getc (FILE * infile)
  84. /* Read next char, skipping over any comments */
  85. /* A comment/newline sequence is returned as a newline */
  86. {
  87.   register int ch;
  88.   
  89.   ch = getc(infile);
  90.   if (ch == '#') {
  91.     do {
  92.       ch = getc(infile);
  93.     } while (ch != '\n' && ch != EOF);
  94.   }
  95.   return ch;
  96. }
  97.  
  98.  
  99. LOCAL unsigned int
  100. read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
  101. /* Read an unsigned decimal integer from the PPM file */
  102. /* Swallows one trailing character after the integer */
  103. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  104. /* This should not be a problem in practice. */
  105. {
  106.   register int ch;
  107.   register unsigned int val;
  108.   
  109.   /* Skip any leading whitespace */
  110.   do {
  111.     ch = pbm_getc(infile);
  112.     if (ch == EOF)
  113.       ERREXIT(cinfo, JERR_INPUT_EOF);
  114.   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
  115.   
  116.   if (ch < '0' || ch > '9')
  117.     ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
  118.   
  119.   val = ch - '0';
  120.   while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
  121.     val *= 10;
  122.     val += ch - '0';
  123.   }
  124.   return val;
  125. }
  126.  
  127.  
  128. /*
  129.  * Read one row of pixels.
  130.  *
  131.  * We provide several different versions depending on input file format.
  132.  * In all cases, input is scaled to the size of JSAMPLE.
  133.  *
  134.  * Note that a really fast path is provided for reading raw files with
  135.  * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
  136.  */
  137.  
  138.  
  139. METHODDEF JDIMENSION
  140. get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  141. /* This version is for reading text-format PGM files with any maxval */
  142. {
  143.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  144.   FILE * infile = source->pub.input_file;
  145.   register JSAMPROW ptr;
  146.   register JSAMPLE *rescale = source->rescale;
  147.   JDIMENSION col;
  148.   
  149.   ptr = source->pub.buffer[0];
  150.   for (col = cinfo->image_width; col > 0; col--) {
  151.     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
  152.   }
  153.   return 1;
  154. }
  155.  
  156.  
  157. METHODDEF JDIMENSION
  158. get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  159. /* This version is for reading text-format PPM files with any maxval */
  160. {
  161.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  162.   FILE * infile = source->pub.input_file;
  163.   register JSAMPROW ptr;
  164.   register JSAMPLE *rescale = source->rescale;
  165.   JDIMENSION col;
  166.   
  167.   ptr = source->pub.buffer[0];
  168.   for (col = cinfo->image_width; col > 0; col--) {
  169.     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
  170.     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
  171.     *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
  172.   }
  173.   return 1;
  174. }
  175.  
  176.  
  177. METHODDEF JDIMENSION
  178. get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  179. /* This version is for reading raw-format PGM files with any maxval */
  180. {
  181.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  182.   register JSAMPROW ptr;
  183.   register U_CHAR * bufferptr;
  184.   register JSAMPLE *rescale = source->rescale;
  185.   JDIMENSION col;
  186.  
  187.   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
  188.     ERREXIT(cinfo, JERR_INPUT_EOF);
  189.   ptr = source->pub.buffer[0];
  190.   bufferptr = source->iobuffer;
  191.   for (col = cinfo->image_width; col > 0; col--) {
  192.     *ptr++ = rescale[UCH(*bufferptr++)];
  193.   }
  194.   return 1;
  195. }
  196.  
  197.  
  198. METHODDEF JDIMENSION
  199. get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  200. /* This version is for reading raw-format PPM files with any maxval */
  201. {
  202.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  203.   register JSAMPROW ptr;
  204.   register U_CHAR * bufferptr;
  205.   register JSAMPLE *rescale = source->rescale;
  206.   JDIMENSION col;
  207.  
  208.   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
  209.     ERREXIT(cinfo, JERR_INPUT_EOF);
  210.   ptr = source->pub.buffer[0];
  211.   bufferptr = source->iobuffer;
  212.   for (col = cinfo->image_width; col > 0; col--) {
  213.     *ptr++ = rescale[UCH(*bufferptr++)];
  214.     *ptr++ = rescale[UCH(*bufferptr++)];
  215.     *ptr++ = rescale[UCH(*bufferptr++)];
  216.   }
  217.   return 1;
  218. }
  219.  
  220.  
  221. METHODDEF JDIMENSION
  222. get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  223. /* This version is for reading raw-format files with maxval = MAXJSAMPLE. */
  224. /* In this case we just read right into the JSAMPLE buffer! */
  225. /* Note that same code works for PPM and PGM files. */
  226. {
  227.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  228.  
  229.   if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
  230.     ERREXIT(cinfo, JERR_INPUT_EOF);
  231.   return 1;
  232. }
  233.  
  234.  
  235. /*
  236.  * Read the file header; return image size and component count.
  237.  */
  238.  
  239. METHODDEF void
  240. start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  241. {
  242.   ppm_source_ptr source = (ppm_source_ptr) sinfo;
  243.   int c;
  244.   unsigned int w, h, maxval;
  245.   boolean can_use_raw;
  246.  
  247.   if (getc(source->pub.input_file) != 'P')
  248.     ERREXIT(cinfo, JERR_PPM_NOT);
  249.  
  250.   c = getc(source->pub.input_file); /* save format discriminator for a sec */
  251.  
  252.   /* while we fetch the remaining header info */
  253.   w = read_pbm_integer(cinfo, source->pub.input_file);
  254.   h = read_pbm_integer(cinfo, source->pub.input_file);
  255.   maxval = read_pbm_integer(cinfo, source->pub.input_file);
  256.  
  257.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  258.     ERREXIT(cinfo, JERR_PPM_NOT);
  259.  
  260.   cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
  261.   cinfo->image_width = (JDIMENSION) w;
  262.   cinfo->image_height = (JDIMENSION) h;
  263.  
  264.   /* Raw PPM/PGM matches JSAMPLE representation iff: */
  265.   can_use_raw = (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR));
  266.  
  267.   switch (c) {
  268.   case '2':            /* it's a text-format PGM file */
  269.     cinfo->input_components = 1;
  270.     cinfo->in_color_space = JCS_GRAYSCALE;
  271.     TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
  272.     source->pub.get_pixel_rows = get_text_gray_row;
  273.     can_use_raw = FALSE;    /* force a rescale array to be made */
  274.     break;
  275.  
  276.   case '3':            /* it's a text-format PPM file */
  277.     cinfo->input_components = 3;
  278.     cinfo->in_color_space = JCS_RGB;
  279.     TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
  280.     source->pub.get_pixel_rows = get_text_rgb_row;
  281.     can_use_raw = FALSE;    /* force a rescale array to be made */
  282.     break;
  283.  
  284.   case '5':            /* it's a raw-format PGM file */
  285.     cinfo->input_components = 1;
  286.     cinfo->in_color_space = JCS_GRAYSCALE;
  287.     TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
  288.     if (can_use_raw)
  289.       source->pub.get_pixel_rows = get_raw_row;
  290.     else
  291.       source->pub.get_pixel_rows = get_scaled_gray_row;
  292.     /* allocate space for I/O buffer: 1 byte/pixel */
  293.     source->iobuffer = (U_CHAR *)
  294.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  295.                   (size_t) (SIZEOF(U_CHAR) * (size_t) w));
  296.     break;
  297.  
  298.   case '6':            /* it's a raw-format PPM file */
  299.     cinfo->input_components = 3;
  300.     cinfo->in_color_space = JCS_RGB;
  301.     TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
  302.     if (can_use_raw)
  303.       source->pub.get_pixel_rows = get_raw_row;
  304.     else
  305.       source->pub.get_pixel_rows = get_scaled_rgb_row;
  306.     /* allocate space for I/O buffer: 3 bytes/pixel */
  307.     source->iobuffer = (U_CHAR *)
  308.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  309.                   (size_t) (3 * SIZEOF(U_CHAR) * (size_t) w));
  310.     break;
  311.  
  312.   default:
  313.     ERREXIT(cinfo, JERR_PPM_NOT);
  314.     break;
  315.   }
  316.  
  317.   /* Create compressor input buffer. */
  318.   source->buffer_width = (JDIMENSION) w * cinfo->input_components;
  319.   if (can_use_raw) {
  320.     /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
  321.     /* Synthesize a JSAMPARRAY pointer structure */
  322.     /* Cast here implies near->far pointer conversion on PCs */
  323.     source->pixrow = (JSAMPROW) source->iobuffer;
  324.     source->pub.buffer = & source->pixrow;
  325.     source->pub.buffer_height = 1;
  326.   } else {
  327.     /* Need to translate anyway, so make a separate sample buffer. */
  328.     source->pub.buffer = (*cinfo->mem->alloc_sarray)
  329.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  330.        source->buffer_width, (JDIMENSION) 1);
  331.     source->pub.buffer_height = 1;
  332.   }
  333.  
  334.   /* Compute the rescaling array if required (we use it for all but raw) */
  335.   if (can_use_raw) {
  336.     source->rescale = NULL;    /* no rescaling required */
  337.   } else {
  338.     INT32 val, half_maxval;
  339.  
  340.     /* On 16-bit-int machines we have to be careful of maxval = 65535 */
  341.     source->rescale = (JSAMPLE *)
  342.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  343.                   (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
  344.     half_maxval = maxval / 2;
  345.     for (val = 0; val <= (INT32) maxval; val++) {
  346.       /* The multiplication here must be done in 32 bits to avoid overflow */
  347.       source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
  348.     }
  349.   }
  350. }
  351.  
  352.  
  353. /*
  354.  * Finish up at the end of the file.
  355.  */
  356.  
  357. METHODDEF void
  358. finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  359. {
  360.   /* no work */
  361. }
  362.  
  363.  
  364. /*
  365.  * The module selection routine for PPM format input.
  366.  */
  367.  
  368. GLOBAL cjpeg_source_ptr
  369. jinit_read_ppm (j_compress_ptr cinfo)
  370. {
  371.   ppm_source_ptr source;
  372.  
  373.   /* Create module interface object */
  374.   source = (ppm_source_ptr)
  375.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  376.                   SIZEOF(ppm_source_struct));
  377.   /* Fill in method ptrs, except get_pixel_rows which start_input sets */
  378.   source->pub.start_input = start_input_ppm;
  379.   source->pub.finish_input = finish_input_ppm;
  380.  
  381.   return (cjpeg_source_ptr) source;
  382. }
  383.  
  384. #endif /* PPM_SUPPORTED */
  385.