home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / compresn / jpegv3sr / jrdppm.c < prev    next >
C/C++ Source or Header  |  1992-01-17  |  9KB  |  325 lines

  1. /*
  2.  * jrdppm.c
  3.  *
  4.  * Copyright (C) 1991, 1992, 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 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; input_init 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.  * These routines are invoked via the methods get_input_row
  20.  * and input_init/term.
  21.  */
  22.  
  23. #include "jinclude.h"
  24.  
  25. #ifdef PPM_SUPPORTED
  26.  
  27.  
  28. static JSAMPLE * rescale;    /* => maxval-remapping array, or NULL */
  29.  
  30.  
  31. /* Portions of this code are based on the PBMPLUS library, which is:
  32. **
  33. ** Copyright (C) 1988 by Jef Poskanzer.
  34. **
  35. ** Permission to use, copy, modify, and distribute this software and its
  36. ** documentation for any purpose and without fee is hereby granted, provided
  37. ** that the above copyright notice appear in all copies and that both that
  38. ** copyright notice and this permission notice appear in supporting
  39. ** documentation.  This software is provided "as is" without express or
  40. ** implied warranty.
  41. */
  42.  
  43.  
  44. LOCAL int
  45. pbm_getc (FILE * file)
  46. /* Read next char, skipping over any comments */
  47. /* A comment/newline sequence is returned as a newline */
  48. {
  49.   register int ch;
  50.   
  51.   ch = getc(file);
  52.   if (ch == '#') {
  53.     do {
  54.       ch = getc(file);
  55.     } while (ch != '\n' && ch != EOF);
  56.   }
  57.   return ch;
  58. }
  59.  
  60.  
  61. LOCAL unsigned int
  62. read_pbm_integer (compress_info_ptr cinfo)
  63. /* Read an unsigned decimal integer from the PPM file */
  64. /* Swallows one trailing character after the integer */
  65. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  66. /* This should not be a problem in practice. */
  67. {
  68.   register int ch;
  69.   register unsigned int val;
  70.   
  71.   /* Skip any leading whitespace */
  72.   do {
  73.     ch = pbm_getc(cinfo->input_file);
  74.     if (ch == EOF)
  75.       ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  76.   } while (ch == ' ' || ch == '\t' || ch == '\n');
  77.   
  78.   if (ch < '0' || ch > '9')
  79.     ERREXIT(cinfo->emethods, "Bogus data in PPM file");
  80.   
  81.   val = ch - '0';
  82.   while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') {
  83.     val *= 10;
  84.     val += ch - '0';
  85.   }
  86.   return val;
  87. }
  88.  
  89.  
  90. /*
  91.  * Read one row of pixels.
  92.  *
  93.  * We provide several different versions depending on input file format.
  94.  * In all cases, input is scaled to the size of JSAMPLE; it's possible that
  95.  * when JSAMPLE is 12 bits, this would not really be desirable.
  96.  *
  97.  * Note that a really fast path is provided for reading raw files with
  98.  * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
  99.  */
  100.  
  101.  
  102. METHODDEF void
  103. get_text_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  104. /* This version is for reading text-format PGM files with any maxval */
  105. {
  106.   register JSAMPROW ptr0;
  107.   register unsigned int val;
  108.   register long col;
  109.   
  110.   ptr0 = pixel_row[0];
  111.   for (col = cinfo->image_width; col > 0; col--) {
  112.     val = read_pbm_integer(cinfo);
  113.     if (rescale != NULL)
  114.       val = rescale[val];
  115.     *ptr0++ = (JSAMPLE) val;
  116.   }
  117. }
  118.  
  119.  
  120. METHODDEF void
  121. get_text_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  122. /* This version is for reading text-format PPM files with any maxval */
  123. {
  124.   register JSAMPROW ptr0, ptr1, ptr2;
  125.   register unsigned int val;
  126.   register long col;
  127.   
  128.   ptr0 = pixel_row[0];
  129.   ptr1 = pixel_row[1];
  130.   ptr2 = pixel_row[2];
  131.   for (col = cinfo->image_width; col > 0; col--) {
  132.     val = read_pbm_integer(cinfo);
  133.     if (rescale != NULL)
  134.       val = rescale[val];
  135.     *ptr0++ = (JSAMPLE) val;
  136.     val = read_pbm_integer(cinfo);
  137.     if (rescale != NULL)
  138.       val = rescale[val];
  139.     *ptr1++ = (JSAMPLE) val;
  140.     val = read_pbm_integer(cinfo);
  141.     if (rescale != NULL)
  142.       val = rescale[val];
  143.     *ptr2++ = (JSAMPLE) val;
  144.   }
  145. }
  146.  
  147.  
  148. METHODDEF void
  149. get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  150. /* This version is for reading raw-format PGM files with any maxval */
  151. {
  152.   register FILE * infile = cinfo->input_file;
  153.   register JSAMPROW ptr0;
  154.   register long col;
  155.   
  156.   ptr0 = pixel_row[0];
  157.   for (col = cinfo->image_width; col > 0; col--) {
  158.     *ptr0++ = rescale[getc(infile)];
  159.   }
  160. }
  161.  
  162.  
  163. METHODDEF void
  164. get_scaled_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  165. /* This version is for reading raw-format PPM files with any maxval */
  166. {
  167.   register FILE * infile = cinfo->input_file;
  168.   register JSAMPROW ptr0, ptr1, ptr2;
  169.   register long col;
  170.   
  171.   ptr0 = pixel_row[0];
  172.   ptr1 = pixel_row[1];
  173.   ptr2 = pixel_row[2];
  174.   for (col = cinfo->image_width; col > 0; col--) {
  175.     *ptr0++ = rescale[getc(infile)];
  176.     *ptr1++ = rescale[getc(infile)];
  177.     *ptr2++ = rescale[getc(infile)];
  178.   }
  179. }
  180.  
  181.  
  182. METHODDEF void
  183. get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  184. /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
  185. {
  186.   register FILE * infile = cinfo->input_file;
  187.   register JSAMPROW ptr0;
  188.   register long col;
  189.   
  190.   ptr0 = pixel_row[0];
  191.   for (col = cinfo->image_width; col > 0; col--) {
  192.     *ptr0++ = (JSAMPLE) getc(infile);
  193.   }
  194. }
  195.  
  196.  
  197. METHODDEF void
  198. get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  199. /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
  200. {
  201.   register FILE * infile = cinfo->input_file;
  202.   register JSAMPROW ptr0, ptr1, ptr2;
  203.   register long col;
  204.   
  205.   ptr0 = pixel_row[0];
  206.   ptr1 = pixel_row[1];
  207.   ptr2 = pixel_row[2];
  208.   for (col = cinfo->image_width; col > 0; col--) {
  209.     *ptr0++ = (JSAMPLE) getc(infile);
  210.     *ptr1++ = (JSAMPLE) getc(infile);
  211.     *ptr2++ = (JSAMPLE) getc(infile);
  212.   }
  213. }
  214.  
  215.  
  216. /*
  217.  * Read the file header; return image size and component count.
  218.  */
  219.  
  220. METHODDEF void
  221. input_init (compress_info_ptr cinfo)
  222. {
  223.   int c;
  224.   unsigned int w, h, maxval;
  225.  
  226.   if (getc(cinfo->input_file) != 'P')
  227.     ERREXIT(cinfo->emethods, "Not a PPM file");
  228.  
  229.   c = getc(cinfo->input_file);    /* save format discriminator for a sec */
  230.  
  231.   w = read_pbm_integer(cinfo);    /* while we fetch the header info */
  232.   h = read_pbm_integer(cinfo);
  233.   maxval = read_pbm_integer(cinfo);
  234.  
  235.   switch (c) {
  236.   case '2':            /* it's a text-format PGM file */
  237.     cinfo->methods->get_input_row = get_text_gray_row;
  238.     cinfo->input_components = 1;
  239.     cinfo->in_color_space = CS_GRAYSCALE;
  240.     break;
  241.  
  242.   case '3':            /* it's a text-format PPM file */
  243.     cinfo->methods->get_input_row = get_text_rgb_row;
  244.     cinfo->input_components = 3;
  245.     cinfo->in_color_space = CS_RGB;
  246.     break;
  247.  
  248.   case '5':            /* it's a raw-format PGM file */
  249.     if (maxval == MAXJSAMPLE)
  250.       cinfo->methods->get_input_row = get_raw_gray_row;
  251.     else
  252.       cinfo->methods->get_input_row = get_scaled_gray_row;
  253.     cinfo->input_components = 1;
  254.     cinfo->in_color_space = CS_GRAYSCALE;
  255.     break;
  256.  
  257.   case '6':            /* it's a raw-format PPM file */
  258.     if (maxval == MAXJSAMPLE)
  259.       cinfo->methods->get_input_row = get_raw_rgb_row;
  260.     else
  261.       cinfo->methods->get_input_row = get_scaled_rgb_row;
  262.     cinfo->input_components = 3;
  263.     cinfo->in_color_space = CS_RGB;
  264.     break;
  265.  
  266.   default:
  267.     ERREXIT(cinfo->emethods, "Not a PPM file");
  268.     break;
  269.   }
  270.  
  271.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  272.     ERREXIT(cinfo->emethods, "Not a PPM file");
  273.  
  274.   /* Compute the rescaling array if necessary */
  275.   /* This saves per-pixel calculation */
  276.   if (maxval == MAXJSAMPLE)
  277.     rescale = NULL;        /* no rescaling required */
  278.   else {
  279.     INT32 val, half_maxval;
  280.  
  281.     /* On 16-bit-int machines we have to be careful of maxval = 65535 */
  282.     rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small)
  283.             ((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
  284.     half_maxval = maxval / 2;
  285.     for (val = 0; val <= (INT32) maxval; val++) {
  286.       /* The multiplication here must be done in 32 bits to avoid overflow */
  287.       rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
  288.     }
  289.   }
  290.  
  291.   cinfo->image_width = w;
  292.   cinfo->image_height = h;
  293.   cinfo->data_precision = BITS_IN_JSAMPLE;
  294. }
  295.  
  296.  
  297. /*
  298.  * Finish up at the end of the file.
  299.  */
  300.  
  301. METHODDEF void
  302. input_term (compress_info_ptr cinfo)
  303. {
  304.   /* no work (we let free_all release the workspace) */
  305. }
  306.  
  307.  
  308. /*
  309.  * The method selection routine for PPM format input.
  310.  * Note that this must be called by the user interface before calling
  311.  * jpeg_compress.  If multiple input formats are supported, the
  312.  * user interface is responsible for discovering the file format and
  313.  * calling the appropriate method selection routine.
  314.  */
  315.  
  316. GLOBAL void
  317. jselrppm (compress_info_ptr cinfo)
  318. {
  319.   cinfo->methods->input_init = input_init;
  320.   /* cinfo->methods->get_input_row is set by input_init */
  321.   cinfo->methods->input_term = input_term;
  322. }
  323.  
  324. #endif /* PPM_SUPPORTED */
  325.