home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR2 / DVPG30FS.ZIP / JRDPPM.C < prev    next >
C/C++ Source or Header  |  1993-10-16  |  13KB  |  456 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. JSAMPARRAY ppm_colormap;    /* colormap pointer */
  28.  
  29. void make_grey_colormap(decompress_info_ptr cinfo, int cmaplen, JSAMPARRAY cmap);
  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. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  45.  
  46. #ifdef HAVE_UNSIGNED_CHAR
  47. typedef unsigned char U_CHAR;
  48. #define UCH(x)    ((int) (x))
  49. #else /* !HAVE_UNSIGNED_CHAR */
  50. #ifdef CHAR_IS_UNSIGNED
  51. typedef char U_CHAR;
  52. #define UCH(x)    ((int) (x))
  53. #else
  54. typedef char U_CHAR;
  55. #define UCH(x)    ((int) (x) & 0xFF)
  56. #endif
  57. #endif /* HAVE_UNSIGNED_CHAR */
  58.  
  59.  
  60. #define    ReadOK(file,buffer,len)    (JFREAD(file,buffer,len) == ((size_t) (len)))
  61.  
  62.  
  63. /*
  64.  * On most systems, reading individual bytes with getc() is drastically less
  65.  * efficient than buffering a row at a time with fread().  But we must
  66.  * allocate the row buffer in near data space on PCs, because we are assuming
  67.  * small-data memory model, wherein fread() can't reach far memory.  If you
  68.  * need to process very wide images on a PC, you may have to use the getc()
  69.  * approach.  In that case, define USE_GETC_INPUT.
  70.  */
  71.  
  72. #ifndef USE_GETC_INPUT
  73. static U_CHAR * row_buffer;    /* holds 1 pixel row's worth of raw input */
  74. #endif
  75.  
  76. static JSAMPLE * rescale;    /* => maxval-remapping array, or NULL */
  77.  
  78.  
  79. LOCAL int
  80. pbm_getc (FILE * file)
  81. /* Read next char, skipping over any comments */
  82. /* A comment/newline sequence is returned as a newline */
  83. {
  84.   register int ch;
  85.  
  86.   ch = getc(file);
  87.   if (ch == '#') {
  88.     do {
  89.       ch = getc(file);
  90.     } while (ch != '\n' && ch != EOF);
  91.   }
  92.   return ch;
  93. }
  94.  
  95.  
  96. LOCAL unsigned int
  97. read_pbm_integer (decompress_info_ptr cinfo)
  98. /* Read an unsigned decimal integer from the PPM file */
  99. /* Swallows one trailing character after the integer */
  100. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  101. /* This should not be a problem in practice. */
  102. {
  103.   register int ch;
  104.   register unsigned int val;
  105.  
  106.   /* Skip any leading whitespace */
  107.   do {
  108.      ch = pbm_getc(cinfo->input_file);
  109.      if (ch == EOF)
  110.         ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  111.   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
  112.  
  113.   if (ch < '0' || ch > '9')
  114.      ERREXIT(cinfo->emethods, "Bogus data in PPM file");
  115.  
  116.   val = ch - '0';
  117.   while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') {
  118.      val *= 10;
  119.      val += ch - '0';
  120.   }
  121.   return val;
  122. }
  123.  
  124.  
  125. /*
  126.  * Read one row of pixels.
  127.  *
  128.  * We provide several different versions depending on input file format.
  129.  * In all cases, input is scaled to the size of JSAMPLE; it's possible that
  130.  * when JSAMPLE is 12 bits, this would not really be desirable.
  131.  *
  132.  * Note that a really fast path is provided for reading raw files with
  133.  * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
  134.  */
  135.  
  136.  
  137. METHODDEF void
  138. get_text_gray_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  139. /* This version is for reading text-format PGM files with any maxval */
  140. {
  141.   register JSAMPROW ptr0;
  142.   register unsigned int val;
  143.   register long col;
  144.  
  145.   ptr0 = pixel_row[0][0];
  146.   for (col = cinfo->image_width; col > 0; col--) {
  147.      val = read_pbm_integer(cinfo);
  148.      if (rescale != NULL)
  149.         val = rescale[val];
  150.      *ptr0++ = (JSAMPLE) val;
  151.   }
  152. }
  153.  
  154.  
  155. METHODDEF void
  156. get_text_rgb_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  157. /* This version is for reading text-format PPM files with any maxval */
  158. {
  159.   register JSAMPROW ptr0, ptr1, ptr2;
  160.   register unsigned int val;
  161.   register long col;
  162.  
  163.   ptr0 = pixel_row[0][0];
  164.   ptr1 = pixel_row[1][0];
  165.   ptr2 = pixel_row[2][0];
  166.   for (col = cinfo->image_width; col > 0; col--) {
  167.      val = read_pbm_integer(cinfo);
  168.      if (rescale != NULL)
  169.         val = rescale[val];
  170.      *ptr0++ = (JSAMPLE) val;
  171.      val = read_pbm_integer(cinfo);
  172.      if (rescale != NULL)
  173.         val = rescale[val];
  174.      *ptr1++ = (JSAMPLE) val;
  175.      val = read_pbm_integer(cinfo);
  176.      if (rescale != NULL)
  177.         val = rescale[val];
  178.      *ptr2++ = (JSAMPLE) val;
  179.   }
  180. }
  181.  
  182.  
  183. #ifdef USE_GETC_INPUT
  184.  
  185.  
  186. METHODDEF void
  187. get_scaled_gray_row (decompress_info_ptr cinfo, JSAMPIAMGE pixel_row)
  188. /* This version is for reading raw-format PGM files with any maxval */
  189. {
  190.   register FILE * infile = cinfo->input_file;
  191.   register JSAMPROW ptr0;
  192.   register long col;
  193.  
  194.   ptr0 = pixel_row[0][0];
  195.   for (col = cinfo->image_width; col > 0; col--) {
  196.      *ptr0++ = rescale[getc(infile)];
  197.   }
  198. }
  199.  
  200.  
  201. METHODDEF void
  202. get_scaled_rgb_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  203. /* This version is for reading raw-format PPM files with any maxval */
  204. {
  205.   register FILE * infile = cinfo->input_file;
  206.   register JSAMPROW ptr0, ptr1, ptr2;
  207.   register long col;
  208.  
  209.   ptr0 = pixel_row[0][0];
  210.   ptr1 = pixel_row[1][0];
  211.   ptr2 = pixel_row[2][0];
  212.   for (col = cinfo->image_width; col > 0; col--) {
  213.      *ptr0++ = rescale[getc(infile)];
  214.      *ptr1++ = rescale[getc(infile)];
  215.      *ptr2++ = rescale[getc(infile)];
  216.   }
  217. }
  218.  
  219.  
  220. METHODDEF void
  221. get_raw_gray_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  222. /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
  223. {
  224.   register FILE * infile = cinfo->input_file;
  225.   register JSAMPROW ptr0;
  226.   register long col;
  227.  
  228.   ptr0 = pixel_row[0];
  229.   for (col = cinfo->image_width; col > 0; col--) {
  230.      *ptr0++ = (JSAMPLE) getc(infile);
  231.   }
  232. }
  233.  
  234.  
  235. METHODDEF void
  236. get_raw_rgb_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  237. /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
  238. {
  239.   register FILE * infile = cinfo->input_file;
  240.   register JSAMPROW ptr0, ptr1, ptr2;
  241.   register long col;
  242.  
  243.   ptr0 = pixel_row[0][0];
  244.   ptr1 = pixel_row[1][0];
  245.   ptr2 = pixel_row[2][0];
  246.   for (col = cinfo->image_width; col > 0; col--) {
  247.      *ptr0++ = (JSAMPLE) getc(infile);
  248.      *ptr1++ = (JSAMPLE) getc(infile);
  249.      *ptr2++ = (JSAMPLE) getc(infile);
  250.   }
  251. }
  252.  
  253.  
  254. #else /* use row buffering */
  255.  
  256.  
  257. METHODDEF void
  258. get_scaled_gray_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  259. /* This version is for reading raw-format PGM files with any maxval */
  260. {
  261.   register JSAMPROW ptr0;
  262.   register U_CHAR * row_bufferptr;
  263.   register long col;
  264.  
  265.   if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
  266.      ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  267.   ptr0 = pixel_row[0][0];
  268.   row_bufferptr = row_buffer;
  269.   for (col = cinfo->image_width; col > 0; col--) {
  270.      *ptr0++ = rescale[UCH(*row_bufferptr++)];
  271.   }
  272. }
  273.  
  274.  
  275. METHODDEF void
  276. get_scaled_rgb_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  277. /* This version is for reading raw-format PPM files with any maxval */
  278. {
  279.   register JSAMPROW ptr0, ptr1, ptr2;
  280.   register U_CHAR * row_bufferptr;
  281.   register long col;
  282.  
  283.   if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
  284.      ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  285.   ptr0 = pixel_row[0][0];
  286.   ptr1 = pixel_row[1][0];
  287.   ptr2 = pixel_row[2][0];
  288.   row_bufferptr = row_buffer;
  289.   for (col = cinfo->image_width; col > 0; col--) {
  290.      *ptr0++ = rescale[UCH(*row_bufferptr++)];
  291.     *ptr1++ = rescale[UCH(*row_bufferptr++)];
  292.     *ptr2++ = rescale[UCH(*row_bufferptr++)];
  293.   }
  294. }
  295.  
  296.  
  297. METHODDEF void
  298. get_raw_gray_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  299. /* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
  300. {
  301.   register JSAMPROW ptr0;
  302.   register U_CHAR * row_bufferptr;
  303.   register long col;
  304.  
  305.   if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
  306.      ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  307.   ptr0 = pixel_row[0][0];
  308.   row_bufferptr = row_buffer;
  309.   for (col = cinfo->image_width; col > 0; col--) {
  310.      *ptr0++ = (JSAMPLE) UCH(*row_bufferptr++);
  311.   }
  312. }
  313.  
  314.  
  315. METHODDEF void
  316. get_raw_rgb_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  317. /* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
  318. {
  319.   register JSAMPROW ptr0, ptr1, ptr2;
  320.   register U_CHAR * row_bufferptr;
  321.   register long col;
  322.  
  323.   if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
  324.      ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
  325.   ptr0 = pixel_row[0][0];
  326.   ptr1 = pixel_row[1][0];
  327.   ptr2 = pixel_row[2][0];
  328.   row_bufferptr = row_buffer;
  329.   for (col = cinfo->image_width; col > 0; col--) {
  330.      *ptr0++ = (JSAMPLE) UCH(*row_bufferptr++);
  331.      *ptr1++ = (JSAMPLE) UCH(*row_bufferptr++);
  332.      *ptr2++ = (JSAMPLE) UCH(*row_bufferptr++);
  333.   }
  334. }
  335.  
  336.  
  337. #endif /* USE_GETC_INPUT */
  338.  
  339.  
  340. /*
  341.  * Read the file header; return image size and component count.
  342.  */
  343.  
  344. METHODDEF void
  345. input_init (decompress_info_ptr cinfo)
  346. {
  347.   int c;
  348.   unsigned int w, h, maxval;
  349.  
  350.   if (getc(cinfo->input_file) != 'P')
  351.      ERREXIT(cinfo->emethods, "Not a PPM file");
  352.  
  353.   c = getc(cinfo->input_file);    /* save format discriminator for a sec */
  354.  
  355.   w = read_pbm_integer(cinfo);    /* while we fetch the header info */
  356.   h = read_pbm_integer(cinfo);
  357.   maxval = read_pbm_integer(cinfo);
  358.  
  359.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  360.      ERREXIT(cinfo->emethods, "Not a PPM file");
  361.  
  362.   switch (c) {
  363.   case '2':            /* it's a text-format PGM file */
  364.      cinfo->methods->get_input_row = get_text_gray_row;
  365.      cinfo->num_components = 1;
  366.      cinfo->jpeg_color_space = CS_GRAYSCALE;
  367.      TRACEMS2(cinfo->emethods, 1, "%ux%u text PGM image", w, h);
  368.      break;
  369.  
  370.   case '3':            /* it's a text-format PPM file */
  371.      cinfo->methods->get_input_row = get_text_rgb_row;
  372.      cinfo->num_components = 3;
  373.      cinfo->jpeg_color_space = CS_RGB;
  374.     TRACEMS2(cinfo->emethods, 1, "%ux%u text PPM image", w, h);
  375.      break;
  376.  
  377.   case '5':            /* it's a raw-format PGM file */
  378.      if (maxval == MAXJSAMPLE)
  379.         cinfo->methods->get_input_row = get_raw_gray_row;
  380.      else
  381.         cinfo->methods->get_input_row = get_scaled_gray_row;
  382.      cinfo->num_components = 1;
  383.      cinfo->jpeg_color_space = CS_GRAYSCALE;
  384. #ifndef USE_GETC_INPUT
  385.      /* allocate space for row buffer: 1 byte/pixel */
  386.      row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
  387.             ((size_t) (SIZEOF(U_CHAR) * (long) w));
  388. #endif
  389.      TRACEMS2(cinfo->emethods, 1, "%ux%u PGM image", w, h);
  390.      break;
  391.  
  392.   case '6':            /* it's a raw-format PPM file */
  393.      if (maxval == MAXJSAMPLE)
  394.         cinfo->methods->get_input_row = get_raw_rgb_row;
  395.      else
  396.         cinfo->methods->get_input_row = get_scaled_rgb_row;
  397.      cinfo->num_components = 3;
  398.      cinfo->jpeg_color_space = CS_RGB;
  399. #ifndef USE_GETC_INPUT
  400.      /* allocate space for row buffer: 3 bytes/pixel */
  401.      row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
  402.             ((size_t) (3 * SIZEOF(U_CHAR) * (long) w));
  403. #endif
  404.      TRACEMS2(cinfo->emethods, 1, "%ux%u PPM image", w, h);
  405.      break;
  406.  
  407.   default:
  408.      ERREXIT(cinfo->emethods, "Not a PPM file");
  409.      break;
  410.   }
  411.  
  412.   /* Compute the rescaling array if necessary */
  413.   /* This saves per-pixel calculation */
  414.   if (maxval == MAXJSAMPLE)
  415.      rescale = NULL;        /* no rescaling required */
  416.   else {
  417.      INT32 val, half_maxval;
  418.  
  419.      /* On 16-bit-int machines we have to be careful of maxval = 65535 */
  420.      rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small)
  421.             ((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
  422.      half_maxval = maxval / 2;
  423.      for (val = 0; val <= (INT32) maxval; val++) {
  424.         /* The multiplication here must be done in 32 bits to avoid overflow */
  425.         rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
  426.      }
  427.   }
  428.  
  429.   cinfo->image_width = w;
  430.   cinfo->image_height = h;
  431.   cinfo->data_precision = BITS_IN_JSAMPLE;
  432. }
  433.  
  434.  
  435.  
  436. /*
  437.  * The method selection routine for PPM format input.
  438.  * Note that this must be called by the user interface before calling
  439.  * jpeg_compress.  If multiple input formats are supported, the
  440.  * user interface is responsible for discovering the file format and
  441.  * calling the appropriate method selection routine.
  442.  */
  443.  
  444. GLOBAL void
  445. j_sel_r_ppm (decompress_info_ptr cinfo)
  446. {
  447.     cinfo->out_color_space = CS_RGB;        /* default ie color output */
  448.  
  449.   cinfo->methods->read_file_header = input_init;
  450.   /* cinfo->methods->get_input_row is set by input_init */
  451. }
  452.  
  453.  
  454.  
  455. #endif /* PPM_SUPPORTED */
  456.