123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- Unit RdColMap;
- { rdcolmap.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
- { This file implements djpeg's "-map file" switch. It reads a source image
- and constructs a colormap to be supplied to the JPEG decompressor.
- Currently, these file formats are supported for the map file:
- GIF: the contents of the GIF's global colormap are used.
- PPM (either text or raw flavor): the entire file is read and
- each unique pixel value is entered in the map.
- Note that reading a large PPM file will be horrendously slow.
- Typically, a PPM-format map file should contain just one pixel
- of each desired color. Such a file can be extracted from an
- ordinary image PPM file with ppmtomap(1).
- Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
- currently implemented. }
- interface
- {$I jconfig.inc}
- uses
- jmorecfg,
- cdjpeg, { Common decls for cjpeg/djpeg applications }
- jdeferr,
- jerror,
- jpeglib;
- { Main entry point from djpeg.c.
- Input: opened input file (from file name argument on command line).
- Output: colormap and actual_number_of_colors fields are set in cinfo. }
- {GLOBAL}
- {$ifdef QUANT_2PASS_SUPPORTED}
- procedure read_color_map (cinfo : j_decompress_ptr; var infile : FILE);
- {$endif} { QUANT_2PASS_SUPPORTED }
- implementation
- {$ifdef QUANT_2PASS_SUPPORTED}
- { otherwise can't quantize to supplied map }
- { Portions of this code are based on the PBMPLUS library, which is:
- *
- * Copyright (C) 1988 by Jef Poskanzer.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. This software is provided "as is" without express or
- * implied warranty.
- }
- { Add a (potentially) new color to the color map. }
- {LOCAL}
- procedure add_map_entry (cinfo : j_decompress_ptr;
- R : int; G : int; B : int);
- var
- colormap0 : JSAMPROW;
- colormap1 : JSAMPROW;
- colormap2 : JSAMPROW;
- ncolors : int;
- index : int;
- begin
- colormap0 := cinfo^.colormap^[0];
- colormap1 := cinfo^.colormap^[1];
- colormap2 := cinfo^.colormap^[2];
- ncolors := cinfo^.actual_number_of_colors;
- { Check for duplicate color. }
- for index := 0 to pred(ncolors) do
- begin
- if (GETJSAMPLE(colormap0^[index]) = R) and
- (GETJSAMPLE(colormap1^[index]) = G) and
- (GETJSAMPLE(colormap2^[index]) = B) then
- exit; { color is already in map }
- end;
- { Check for map overflow. }
- if (ncolors >= (MAXJSAMPLE+1)) then
- ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
- { OK, add color to map. }
- colormap0^[ncolors] := JSAMPLE (R);
- colormap1^[ncolors] := JSAMPLE (G);
- colormap2^[ncolors] := JSAMPLE (B);
- Inc(cinfo^.actual_number_of_colors);
- end;
- { Extract color map from a GIF file. }
- {LOCAL}
- procedure read_gif_map (cinfo : j_decompress_ptr; var infile : file);
- var
- header : packed array[1..13-1] of byte;
- i, colormaplen : int;
- var
- color : RGBtype;
- var
- count : int;
- begin
- { Initial 'G' has already been read by read_color_map }
- { Read the rest of the GIF header and logical screen descriptor }
- blockread(infile, header, 13-1, count);
- if (count <> 13-1) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- { Verify GIF Header }
- if (header[1] <> byte('I')) or (header[2] <> byte('F')) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- { There must be a global color map. }
- if ((header[10] and $80) = 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- { OK, fetch it. }
- colormaplen := 2 shl (header[10] and $07);
- for i := 0 to pred(colormaplen) do
- begin
- blockread(infile, color, 3, count);
- if (count <> 3) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- add_map_entry(cinfo,
- color.R shl (BITS_IN_JSAMPLE-8),
- color.G shl (BITS_IN_JSAMPLE-8),
- color.B shl (BITS_IN_JSAMPLE-8));
- end;
- end;
- {$IFDEF PPM}
- { Support routines for reading PPM }
- {LOCAL}
- function pbm_getc (var infile : FILE) : int;
- { Read next char, skipping over any comments }
- { A comment/newline sequence is returned as a newline }
- var
- {register} ch : int;
- begin
- ch := getc(infile);
- if (ch = '#') then
- begin
- repeat
- ch := getc(infile);
- until not (ch <> '\n') and not EOF(infile);
- end;
- pbm_get := ch;
- end;
- {LOCAL}
- function read_pbm_integer (cinfo : j_decompress_ptr;
- var infile : FILE) : uInt;
- { Read an unsigned decimal integer from the PPM file }
- { Swallows one trailing character after the integer }
- { Note that on a 16-bit-int machine, only values up to 64k can be read. }
- { This should not be a problem in practice. }
- var
- {register} ch : int;
- {register} val : uInt;
- begin
- { Skip any leading whitespace }
- repeat
- ch := pbm_getc(infile);
- if EOF(infile) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- until (ch <> ' ') and (ch <> '\t') and (ch <> '\n') and (ch <> '\r');
- if (ch < '0') or (ch > '9') then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- val := ch - '0';
- ch := pbm_getc(infile);
- while (ch >= '0') and (ch <= '9') do
- begin
- val := val * 10;
- Inc(val, ch - '0');
- ch := pbm_getc(infile);
- end;
- read_pbm_integer := val;
- end;
- { Extract color map from a PPM file. }
- {LOCAL}
- procedure read_ppm_map (cinfo : j_decompress_ptr; var infile : FILE);
- var
- c : int;
- w, h, maxval, row, col : uInt;
- R, G, B : int;
- begin
- { Initial 'P' has already been read by read_color_map }
- c := getc(infile); { save format discriminator for a sec }
- { while we fetch the remaining header info }
- w := read_pbm_integer(cinfo, infile);
- h := read_pbm_integer(cinfo, infile);
- maxval := read_pbm_integer(cinfo, infile);
- if (w <= 0) or (h <= 0) or (maxval <= 0) then { error check }
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- { For now, we don't support rescaling from an unusual maxval. }
- if (maxval <> (unsigned int) MAXJSAMPLE) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- case (c) of
- '3': { it's a text-format PPM file }
- for row := 0 to pred(h) do
- begin
- for col := 0 to pred(w) do
- begin
- R := read_pbm_integer(cinfo, infile);
- G := read_pbm_integer(cinfo, infile);
- B := read_pbm_integer(cinfo, infile);
- add_map_entry(cinfo, R, G, B);
- end;
- end;
- '6': { it's a raw-format PPM file }
- for row := 0 to pred(h) do
- begin
- for col := 0 to pred(w) do
- begin
- R := pbm_getc(infile);
- G := pbm_getc(infile);
- B := pbm_getc(infile);
- if (R = EOF) or (G = EOF) or (B = EOF) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- add_map_entry(cinfo, R, G, B);
- end;
- end;
- else
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- end;
- end;
- {$ENDIF}
- { Main entry point from djpeg.c.
- Input: opened input file (from file name argument on command line).
- Output: colormap and actual_number_of_colors fields are set in cinfo. }
- {GLOBAL}
- procedure read_color_map (cinfo : j_decompress_ptr;
- var infile : FILE);
- var
- ch : char;
- begin
- { Allocate space for a color map of maximum supported size. }
- cinfo^.colormap := cinfo^.mem^.alloc_sarray
- (j_common_ptr (cinfo), JPOOL_IMAGE,
- JDIMENSION (MAXJSAMPLE+1), JDIMENSION (3));
- cinfo^.actual_number_of_colors := 0; { initialize map to empty }
- { Read first byte to determine file format }
- BlockRead(infile, ch, 1);
- case ch of
- 'G': read_gif_map(cinfo, infile);
- {$IFDEF PPM}
- 'P': read_ppm_map(cinfo, infile);
- {$ENDIF}
- else
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_CMAP_FILE);
- end;
- end;
- {$endif} { QUANT_2PASS_SUPPORTED }
- end.
|