rdcolmap.pas 7.7 KB

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