home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GRAPHICS / jpeglib_5a.lzh / JPEG_5A / rdcolmap.c < prev    next >
Text File  |  1995-01-20  |  7KB  |  258 lines

  1. /*
  2.  * rdcolmap.c
  3.  *
  4.  * Copyright (C) 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 implements djpeg's "-map file" switch.  It reads a source image
  9.  * and constructs a colormap to be supplied to the JPEG decompressor.
  10.  *
  11.  * Currently, these file formats are supported for the map file:
  12.  *   GIF: the contents of the GIF's global colormap are used.
  13.  *   PPM (either text or raw flavor): the entire file is read and
  14.  *      each unique pixel value is entered in the map.
  15.  * Note that reading a large PPM file will be horrendously slow.
  16.  * Typically, a PPM-format map file should contain just one pixel
  17.  * of each desired color.  Such a file can be extracted from an
  18.  * ordinary image PPM file with ppmtomap(1).
  19.  *
  20.  * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
  21.  * currently implemented.
  22.  */
  23.  
  24. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  25.  
  26. #ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
  27.  
  28. /* Portions of this code are based on the PBMPLUS library, which is:
  29. **
  30. ** Copyright (C) 1988 by Jef Poskanzer.
  31. **
  32. ** Permission to use, copy, modify, and distribute this software and its
  33. ** documentation for any purpose and without fee is hereby granted, provided
  34. ** that the above copyright notice appear in all copies and that both that
  35. ** copyright notice and this permission notice appear in supporting
  36. ** documentation.  This software is provided "as is" without express or
  37. ** implied warranty.
  38. */
  39.  
  40.  
  41. /*
  42.  * Add a (potentially) new color to the color map.
  43.  */
  44.  
  45. LOCAL void
  46. add_map_entry (j_decompress_ptr cinfo, int R, int G, int B)
  47. {
  48.   JSAMPROW colormap0 = cinfo->colormap[0];
  49.   JSAMPROW colormap1 = cinfo->colormap[1];
  50.   JSAMPROW colormap2 = cinfo->colormap[2];
  51.   int ncolors = cinfo->actual_number_of_colors;
  52.   int index;
  53.  
  54.   /* Check for duplicate color. */
  55.   for (index = 0; index < ncolors; index++) {
  56.     if (GETJSAMPLE(colormap0[index]) == R &&
  57.     GETJSAMPLE(colormap1[index]) == G &&
  58.     GETJSAMPLE(colormap2[index]) == B)
  59.       return;            /* color is already in map */
  60.   }
  61.  
  62.   /* Check for map overflow. */
  63.   if (ncolors >= (MAXJSAMPLE+1))
  64.     ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
  65.  
  66.   /* OK, add color to map. */
  67.   colormap0[ncolors] = (JSAMPLE) R;
  68.   colormap1[ncolors] = (JSAMPLE) G;
  69.   colormap2[ncolors] = (JSAMPLE) B;
  70.   cinfo->actual_number_of_colors++;
  71. }
  72.  
  73.  
  74. /*
  75.  * Extract color map from a GIF file.
  76.  */
  77.  
  78. LOCAL void
  79. read_gif_map (j_decompress_ptr cinfo, FILE * infile)
  80. {
  81.   int header[13];
  82.   int i, colormaplen;
  83.   int R, G, B;
  84.  
  85.   /* Initial 'G' has already been read by read_color_map */
  86.   /* Read the rest of the GIF header and logical screen descriptor */
  87.   for (i = 1; i < 13; i++) {
  88.     if ((header[i] = getc(infile)) == EOF)
  89.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  90.   }
  91.  
  92.   /* Verify GIF Header */
  93.   if (header[1] != 'I' || header[2] != 'F')
  94.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  95.  
  96.   /* There must be a global color map. */
  97.   if ((header[10] & 0x80) == 0)
  98.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  99.  
  100.   /* OK, fetch it. */
  101.   colormaplen = 2 << (header[10] & 0x07);
  102.  
  103.   for (i = 0; i < colormaplen; i++) {
  104.     R = getc(infile);
  105.     G = getc(infile);
  106.     B = getc(infile);
  107.     if (R == EOF || G == EOF || B == EOF)
  108.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  109.     add_map_entry(cinfo,
  110.           R << (BITS_IN_JSAMPLE-8),
  111.           G << (BITS_IN_JSAMPLE-8),
  112.           B << (BITS_IN_JSAMPLE-8));
  113.   }
  114. }
  115.  
  116.  
  117. /* Support routines for reading PPM */
  118.  
  119.  
  120. LOCAL int
  121. pbm_getc (FILE * infile)
  122. /* Read next char, skipping over any comments */
  123. /* A comment/newline sequence is returned as a newline */
  124. {
  125.   register int ch;
  126.   
  127.   ch = getc(infile);
  128.   if (ch == '#') {
  129.     do {
  130.       ch = getc(infile);
  131.     } while (ch != '\n' && ch != EOF);
  132.   }
  133.   return ch;
  134. }
  135.  
  136.  
  137. LOCAL unsigned int
  138. read_pbm_integer (j_decompress_ptr cinfo, FILE * infile)
  139. /* Read an unsigned decimal integer from the PPM file */
  140. /* Swallows one trailing character after the integer */
  141. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  142. /* This should not be a problem in practice. */
  143. {
  144.   register int ch;
  145.   register unsigned int val;
  146.   
  147.   /* Skip any leading whitespace */
  148.   do {
  149.     ch = pbm_getc(infile);
  150.     if (ch == EOF)
  151.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  152. #ifndef OSK
  153.   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
  154. #else
  155.   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
  156. #endif
  157.   
  158.   if (ch < '0' || ch > '9')
  159.     ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
  160.   
  161.   val = ch - '0';
  162.   while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
  163.     val *= 10;
  164.     val += ch - '0';
  165.   }
  166.   return val;
  167. }
  168.  
  169.  
  170. /*
  171.  * Extract color map from a PPM file.
  172.  */
  173.  
  174. LOCAL void
  175. read_ppm_map (j_decompress_ptr cinfo, FILE * infile)
  176. {
  177.   int c;
  178.   unsigned int w, h, maxval, row, col;
  179.   int R, G, B;
  180.  
  181.   /* Initial 'P' has already been read by read_color_map */
  182.   c = getc(infile);        /* save format discriminator for a sec */
  183.  
  184.   /* while we fetch the remaining header info */
  185.   w = read_pbm_integer(cinfo, infile);
  186.   h = read_pbm_integer(cinfo, infile);
  187.   maxval = read_pbm_integer(cinfo, infile);
  188.  
  189.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  190.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  191.  
  192.   /* For now, we don't support rescaling from an unusual maxval. */
  193.   if (maxval != (unsigned int) MAXJSAMPLE)
  194.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  195.  
  196.   switch (c) {
  197.   case '3':            /* it's a text-format PPM file */
  198.     for (row = 0; row < h; row++) {
  199.       for (col = 0; col < w; col++) {
  200.     R = read_pbm_integer(cinfo, infile);
  201.     G = read_pbm_integer(cinfo, infile);
  202.     B = read_pbm_integer(cinfo, infile);
  203.     add_map_entry(cinfo, R, G, B);
  204.       }
  205.     }
  206.     break;
  207.  
  208.   case '6':            /* it's a raw-format PPM file */
  209.     for (row = 0; row < h; row++) {
  210.       for (col = 0; col < w; col++) {
  211.     R = pbm_getc(infile);
  212.     G = pbm_getc(infile);
  213.     B = pbm_getc(infile);
  214.     if (R == EOF || G == EOF || B == EOF)
  215.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  216.     add_map_entry(cinfo, R, G, B);
  217.       }
  218.     }
  219.     break;
  220.  
  221.   default:
  222.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  223.     break;
  224.   }
  225. }
  226.  
  227.  
  228. /*
  229.  * Main entry point from djpeg.c.
  230.  *  Input: opened input file (from file name argument on command line).
  231.  *  Output: colormap and actual_number_of_colors fields are set in cinfo.
  232.  */
  233.  
  234. GLOBAL void
  235. read_color_map (j_decompress_ptr cinfo, FILE * infile)
  236. {
  237.   /* Allocate space for a color map of maximum supported size. */
  238.   cinfo->colormap = (*cinfo->mem->alloc_sarray)
  239.     ((j_common_ptr) cinfo, JPOOL_IMAGE,
  240.      (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3);
  241.   cinfo->actual_number_of_colors = 0; /* initialize map to empty */
  242.  
  243.   /* Read first byte to determine file format */
  244.   switch (getc(infile)) {
  245.   case 'G':
  246.     read_gif_map(cinfo, infile);
  247.     break;
  248.   case 'P':
  249.     read_ppm_map(cinfo, infile);
  250.     break;
  251.   default:
  252.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  253.     break;
  254.   }
  255. }
  256.  
  257. #endif /* QUANT_2PASS_SUPPORTED */
  258.