Repo for the search and displace ingest module that takes odf, docx and pdf and transforms it into .md to be used with search and displace operations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1009 lines
35 KiB

3 years ago
  1. unit imjquant1;
  2. { This file contains 1-pass color quantization (color mapping) routines.
  3. These routines provide mapping to a fixed color map using equally spaced
  4. color values. Optional Floyd-Steinberg or ordered dithering is available. }
  5. { Original: jquant1.c; Copyright (C) 1991-1996, Thomas G. Lane. }
  6. interface
  7. {$I imjconfig.inc}
  8. uses
  9. imjpeglib;
  10. {GLOBAL}
  11. procedure jinit_1pass_quantizer (cinfo : j_decompress_ptr);
  12. implementation
  13. uses
  14. imjmorecfg,
  15. imjdeferr,
  16. imjerror,
  17. imjutils;
  18. { The main purpose of 1-pass quantization is to provide a fast, if not very
  19. high quality, colormapped output capability. A 2-pass quantizer usually
  20. gives better visual quality; however, for quantized grayscale output this
  21. quantizer is perfectly adequate. Dithering is highly recommended with this
  22. quantizer, though you can turn it off if you really want to.
  23. In 1-pass quantization the colormap must be chosen in advance of seeing the
  24. image. We use a map consisting of all combinations of Ncolors[i] color
  25. values for the i'th component. The Ncolors[] values are chosen so that
  26. their product, the total number of colors, is no more than that requested.
  27. (In most cases, the product will be somewhat less.)
  28. Since the colormap is orthogonal, the representative value for each color
  29. component can be determined without considering the other components;
  30. then these indexes can be combined into a colormap index by a standard
  31. N-dimensional-array-subscript calculation. Most of the arithmetic involved
  32. can be precalculated and stored in the lookup table colorindex[].
  33. colorindex[i][j] maps pixel value j in component i to the nearest
  34. representative value (grid plane) for that component; this index is
  35. multiplied by the array stride for component i, so that the
  36. index of the colormap entry closest to a given pixel value is just
  37. sum( colorindex[component-number][pixel-component-value] )
  38. Aside from being fast, this scheme allows for variable spacing between
  39. representative values with no additional lookup cost.
  40. If gamma correction has been applied in color conversion, it might be wise
  41. to adjust the color grid spacing so that the representative colors are
  42. equidistant in linear space. At this writing, gamma correction is not
  43. implemented by jdcolor, so nothing is done here. }
  44. { Declarations for ordered dithering.
  45. We use a standard 16x16 ordered dither array. The basic concept of ordered
  46. dithering is described in many references, for instance Dale Schumacher's
  47. chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
  48. In place of Schumacher's comparisons against a "threshold" value, we add a
  49. "dither" value to the input pixel and then round the result to the nearest
  50. output value. The dither value is equivalent to (0.5 - threshold) times
  51. the distance between output values. For ordered dithering, we assume that
  52. the output colors are equally spaced; if not, results will probably be
  53. worse, since the dither may be too much or too little at a given point.
  54. The normal calculation would be to form pixel value + dither, range-limit
  55. this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
  56. We can skip the separate range-limiting step by extending the colorindex
  57. table in both directions. }
  58. const
  59. ODITHER_SIZE = 16; { dimension of dither matrix }
  60. { NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break }
  61. ODITHER_CELLS = (ODITHER_SIZE*ODITHER_SIZE); { # cells in matrix }
  62. ODITHER_MASK = (ODITHER_SIZE-1); { mask for wrapping around counters }
  63. type
  64. ODITHER_vector = Array[0..ODITHER_SIZE-1] of int;
  65. ODITHER_MATRIX = Array[0..ODITHER_SIZE-1] of ODITHER_vector;
  66. {ODITHER_MATRIX_PTR = ^array[0..ODITHER_SIZE-1] of int;}
  67. ODITHER_MATRIX_PTR = ^ODITHER_MATRIX;
  68. const
  69. base_dither_matrix : Array[0..ODITHER_SIZE-1,0..ODITHER_SIZE-1] of UINT8
  70. = (
  71. { Bayer's order-4 dither array. Generated by the code given in
  72. Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
  73. The values in this array must range from 0 to ODITHER_CELLS-1. }
  74. ( 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 ),
  75. ( 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 ),
  76. ( 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 ),
  77. ( 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 ),
  78. ( 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 ),
  79. ( 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 ),
  80. ( 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 ),
  81. ( 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 ),
  82. ( 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 ),
  83. ( 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 ),
  84. ( 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 ),
  85. ( 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 ),
  86. ( 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 ),
  87. ( 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 ),
  88. ( 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 ),
  89. ( 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 )
  90. );
  91. { Declarations for Floyd-Steinberg dithering.
  92. Errors are accumulated into the array fserrors[], at a resolution of
  93. 1/16th of a pixel count. The error at a given pixel is propagated
  94. to its not-yet-processed neighbors using the standard F-S fractions,
  95. ... (here) 7/16
  96. 3/16 5/16 1/16
  97. We work left-to-right on even rows, right-to-left on odd rows.
  98. We can get away with a single array (holding one row's worth of errors)
  99. by using it to store the current row's errors at pixel columns not yet
  100. processed, but the next row's errors at columns already processed. We
  101. need only a few extra variables to hold the errors immediately around the
  102. current column. (If we are lucky, those variables are in registers, but
  103. even if not, they're probably cheaper to access than array elements are.)
  104. The fserrors[] array is indexed [component#][position].
  105. We provide (#columns + 2) entries per component; the extra entry at each
  106. end saves us from special-casing the first and last pixels.
  107. Note: on a wide image, we might not have enough room in a PC's near data
  108. segment to hold the error array; so it is allocated with alloc_large. }
  109. {$ifdef BITS_IN_JSAMPLE_IS_8}
  110. type
  111. FSERROR = INT16; { 16 bits should be enough }
  112. LOCFSERROR = int; { use 'int' for calculation temps }
  113. {$else}
  114. type
  115. FSERROR = INT32; { may need more than 16 bits }
  116. LOCFSERROR = INT32; { be sure calculation temps are big enough }
  117. {$endif}
  118. type
  119. jFSError = 0..(MaxInt div SIZEOF(FSERROR))-1;
  120. FS_ERROR_FIELD = array[jFSError] of FSERROR;
  121. FS_ERROR_FIELD_PTR = ^FS_ERROR_FIELD;{far}
  122. { pointer to error array (in FAR storage!) }
  123. FSERRORPTR = ^FSERROR;
  124. { Private subobject }
  125. const
  126. MAX_Q_COMPS = 4; { max components I can handle }
  127. type
  128. my_cquantize_ptr = ^my_cquantizer;
  129. my_cquantizer = record
  130. pub : jpeg_color_quantizer; { public fields }
  131. { Initially allocated colormap is saved here }
  132. sv_colormap : JSAMPARRAY; { The color map as a 2-D pixel array }
  133. sv_actual : int; { number of entries in use }
  134. colorindex : JSAMPARRAY; { Precomputed mapping for speed }
  135. { colorindex[i][j] = index of color closest to pixel value j in component i,
  136. premultiplied as described above. Since colormap indexes must fit into
  137. JSAMPLEs, the entries of this array will too. }
  138. is_padded : boolean; { is the colorindex padded for odither? }
  139. Ncolors : array[0..MAX_Q_COMPS-1] of int;
  140. { # of values alloced to each component }
  141. { Variables for ordered dithering }
  142. row_index : int; { cur row's vertical index in dither matrix }
  143. odither : array[0..MAX_Q_COMPS-1] of ODITHER_MATRIX_PTR;
  144. { one dither array per component }
  145. { Variables for Floyd-Steinberg dithering }
  146. fserrors : array[0..MAX_Q_COMPS-1] of FS_ERROR_FIELD_PTR;
  147. { accumulated errors }
  148. on_odd_row : boolean; { flag to remember which row we are on }
  149. end;
  150. { Policy-making subroutines for create_colormap and create_colorindex.
  151. These routines determine the colormap to be used. The rest of the module
  152. only assumes that the colormap is orthogonal.
  153. * select_ncolors decides how to divvy up the available colors
  154. among the components.
  155. * output_value defines the set of representative values for a component.
  156. * largest_input_value defines the mapping from input values to
  157. representative values for a component.
  158. Note that the latter two routines may impose different policies for
  159. different components, though this is not currently done. }
  160. {LOCAL}
  161. function select_ncolors (cinfo : j_decompress_ptr;
  162. var Ncolors : array of int) : int;
  163. { Determine allocation of desired colors to components, }
  164. { and fill in Ncolors[] array to indicate choice. }
  165. { Return value is total number of colors (product of Ncolors[] values). }
  166. var
  167. nc : int;
  168. max_colors : int;
  169. total_colors, iroot, i, j : int;
  170. changed : boolean;
  171. temp : long;
  172. const
  173. RGB_order:array[0..2] of int = (RGB_GREEN, RGB_RED, RGB_BLUE);
  174. begin
  175. nc := cinfo^.out_color_components; { number of color components }
  176. max_colors := cinfo^.desired_number_of_colors;
  177. { We can allocate at least the nc'th root of max_colors per component. }
  178. { Compute floor(nc'th root of max_colors). }
  179. iroot := 1;
  180. repeat
  181. Inc(iroot);
  182. temp := iroot; { set temp = iroot ** nc }
  183. for i := 1 to pred(nc) do
  184. temp := temp * iroot;
  185. until (temp > long(max_colors)); { repeat till iroot exceeds root }
  186. Dec(iroot); { now iroot = floor(root) }
  187. { Must have at least 2 color values per component }
  188. if (iroot < 2) then
  189. ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_FEW_COLORS, int(temp));
  190. { Initialize to iroot color values for each component }
  191. total_colors := 1;
  192. for i := 0 to pred(nc) do
  193. begin
  194. Ncolors[i] := iroot;
  195. total_colors := total_colors * iroot;
  196. end;
  197. { We may be able to increment the count for one or more components without
  198. exceeding max_colors, though we know not all can be incremented.
  199. Sometimes, the first component can be incremented more than once!
  200. (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
  201. In RGB colorspace, try to increment G first, then R, then B. }
  202. repeat
  203. changed := FALSE;
  204. for i := 0 to pred(nc) do
  205. begin
  206. if cinfo^.out_color_space = JCS_RGB then
  207. j := RGB_order[i]
  208. else
  209. j := i;
  210. { calculate new total_colors if Ncolors[j] is incremented }
  211. temp := total_colors div Ncolors[j];
  212. temp := temp * (Ncolors[j]+1); { done in long arith to avoid oflo }
  213. if (temp > long(max_colors)) then
  214. break; { won't fit, done with this pass }
  215. Inc(Ncolors[j]); { OK, apply the increment }
  216. total_colors := int(temp);
  217. changed := TRUE;
  218. end;
  219. until not changed;
  220. select_ncolors := total_colors;
  221. end;
  222. {LOCAL}
  223. function output_value (cinfo : j_decompress_ptr;
  224. ci : int; j : int; maxj : int) : int;
  225. { Return j'th output value, where j will range from 0 to maxj }
  226. { The output values must fall in 0..MAXJSAMPLE in increasing order }
  227. begin
  228. { We always provide values 0 and MAXJSAMPLE for each component;
  229. any additional values are equally spaced between these limits.
  230. (Forcing the upper and lower values to the limits ensures that
  231. dithering can't produce a color outside the selected gamut.) }
  232. output_value := int (( INT32(j) * MAXJSAMPLE + maxj div 2) div maxj);
  233. end;
  234. {LOCAL}
  235. function largest_input_value (cinfo : j_decompress_ptr;
  236. ci : int; j : int; maxj : int) : int;
  237. { Return largest input value that should map to j'th output value }
  238. { Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE }
  239. begin
  240. { Breakpoints are halfway between values returned by output_value }
  241. largest_input_value := int (( INT32(2*j + 1) * MAXJSAMPLE +
  242. maxj) div (2*maxj));
  243. end;
  244. { Create the colormap. }
  245. {LOCAL}
  246. procedure create_colormap (cinfo : j_decompress_ptr);
  247. var
  248. cquantize : my_cquantize_ptr;
  249. colormap : JSAMPARRAY; { Created colormap }
  250. total_colors : int; { Number of distinct output colors }
  251. i,j,k, nci, blksize, blkdist, ptr, val : int;
  252. begin
  253. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  254. { Select number of colors for each component }
  255. total_colors := select_ncolors(cinfo, cquantize^.Ncolors);
  256. { Report selected color counts }
  257. {$IFDEF DEBUG}
  258. if (cinfo^.out_color_components = 3) then
  259. TRACEMS4(j_common_ptr(cinfo), 1, JTRC_QUANT_3_NCOLORS,
  260. total_colors, cquantize^.Ncolors[0],
  261. cquantize^.Ncolors[1], cquantize^.Ncolors[2])
  262. else
  263. TRACEMS1(j_common_ptr(cinfo), 1, JTRC_QUANT_NCOLORS, total_colors);
  264. {$ENDIF}
  265. { Allocate and fill in the colormap. }
  266. { The colors are ordered in the map in standard row-major order, }
  267. { i.e. rightmost (highest-indexed) color changes most rapidly. }
  268. colormap := cinfo^.mem^.alloc_sarray(
  269. j_common_ptr(cinfo), JPOOL_IMAGE,
  270. JDIMENSION(total_colors), JDIMENSION(cinfo^.out_color_components));
  271. { blksize is number of adjacent repeated entries for a component }
  272. { blkdist is distance between groups of identical entries for a component }
  273. blkdist := total_colors;
  274. for i := 0 to pred(cinfo^.out_color_components) do
  275. begin
  276. { fill in colormap entries for i'th color component }
  277. nci := cquantize^.Ncolors[i]; { # of distinct values for this color }
  278. blksize := blkdist div nci;
  279. for j := 0 to pred(nci) do
  280. begin
  281. { Compute j'th output value (out of nci) for component }
  282. val := output_value(cinfo, i, j, nci-1);
  283. { Fill in all colormap entries that have this value of this component }
  284. ptr := j * blksize;
  285. while (ptr < total_colors) do
  286. begin
  287. { fill in blksize entries beginning at ptr }
  288. for k := 0 to pred(blksize) do
  289. colormap^[i]^[ptr+k] := JSAMPLE(val);
  290. Inc(ptr, blkdist);
  291. end;
  292. end;
  293. blkdist := blksize; { blksize of this color is blkdist of next }
  294. end;
  295. { Save the colormap in private storage,
  296. where it will survive color quantization mode changes. }
  297. cquantize^.sv_colormap := colormap;
  298. cquantize^.sv_actual := total_colors;
  299. end;
  300. { Create the color index table. }
  301. {LOCAL}
  302. procedure create_colorindex (cinfo : j_decompress_ptr);
  303. var
  304. cquantize : my_cquantize_ptr;
  305. indexptr,
  306. help_indexptr : JSAMPROW; { for negative offsets }
  307. i,j,k, nci, blksize, val, pad : int;
  308. begin
  309. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  310. { For ordered dither, we pad the color index tables by MAXJSAMPLE in
  311. each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
  312. This is not necessary in the other dithering modes. However, we
  313. flag whether it was done in case user changes dithering mode. }
  314. if (cinfo^.dither_mode = JDITHER_ORDERED) then
  315. begin
  316. pad := MAXJSAMPLE*2;
  317. cquantize^.is_padded := TRUE;
  318. end
  319. else
  320. begin
  321. pad := 0;
  322. cquantize^.is_padded := FALSE;
  323. end;
  324. cquantize^.colorindex := cinfo^.mem^.alloc_sarray
  325. (j_common_ptr(cinfo), JPOOL_IMAGE,
  326. JDIMENSION(MAXJSAMPLE+1 + pad),
  327. JDIMENSION(cinfo^.out_color_components));
  328. { blksize is number of adjacent repeated entries for a component }
  329. blksize := cquantize^.sv_actual;
  330. for i := 0 to pred(cinfo^.out_color_components) do
  331. begin
  332. { fill in colorindex entries for i'th color component }
  333. nci := cquantize^.Ncolors[i]; { # of distinct values for this color }
  334. blksize := blksize div nci;
  335. { adjust colorindex pointers to provide padding at negative indexes. }
  336. if (pad <> 0) then
  337. Inc(JSAMPLE_PTR(cquantize^.colorindex^[i]), MAXJSAMPLE);
  338. { in loop, val = index of current output value, }
  339. { and k = largest j that maps to current val }
  340. indexptr := cquantize^.colorindex^[i];
  341. val := 0;
  342. k := largest_input_value(cinfo, i, 0, nci-1);
  343. for j := 0 to MAXJSAMPLE do
  344. begin
  345. while (j > k) do { advance val if past boundary }
  346. begin
  347. Inc(val);
  348. k := largest_input_value(cinfo, i, val, nci-1);
  349. end;
  350. { premultiply so that no multiplication needed in main processing }
  351. indexptr^[j] := JSAMPLE (val * blksize);
  352. end;
  353. { Pad at both ends if necessary }
  354. if (pad <> 0) then
  355. begin
  356. help_indexptr := indexptr;
  357. { adjust the help pointer to avoid negative offsets }
  358. Dec(JSAMPLE_PTR(help_indexptr), MAXJSAMPLE);
  359. for j := 1 to MAXJSAMPLE do
  360. begin
  361. {indexptr^[-j] := indexptr^[0];}
  362. help_indexptr^[MAXJSAMPLE-j] := indexptr^[0];
  363. indexptr^[MAXJSAMPLE+j] := indexptr^[MAXJSAMPLE];
  364. end;
  365. end;
  366. end;
  367. end;
  368. { Create an ordered-dither array for a component having ncolors
  369. distinct output values. }
  370. {LOCAL}
  371. function make_odither_array (cinfo : j_decompress_ptr;
  372. ncolors : int) : ODITHER_MATRIX_PTR;
  373. var
  374. odither : ODITHER_MATRIX_PTR;
  375. j, k : int;
  376. num, den : INT32;
  377. begin
  378. odither := ODITHER_MATRIX_PTR (
  379. cinfo^.mem^.alloc_small(j_common_ptr(cinfo), JPOOL_IMAGE,
  380. SIZEOF(ODITHER_MATRIX)));
  381. { The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
  382. Hence the dither value for the matrix cell with fill order f
  383. (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
  384. On 16-bit-int machine, be careful to avoid overflow. }
  385. den := 2 * ODITHER_CELLS * ( INT32(ncolors - 1));
  386. for j := 0 to pred(ODITHER_SIZE) do
  387. begin
  388. for k := 0 to pred(ODITHER_SIZE) do
  389. begin
  390. num := ( INT32(ODITHER_CELLS-1 - 2*( int(base_dither_matrix[j][k]))))
  391. * MAXJSAMPLE;
  392. { Ensure round towards zero despite C's lack of consistency
  393. about rounding negative values in integer division... }
  394. if num<0 then
  395. odither^[j][k] := int (-((-num) div den))
  396. else
  397. odither^[j][k] := int (num div den);
  398. end;
  399. end;
  400. make_odither_array := odither;
  401. end;
  402. { Create the ordered-dither tables.
  403. Components having the same number of representative colors may
  404. share a dither table. }
  405. {LOCAL}
  406. procedure create_odither_tables (cinfo : j_decompress_ptr);
  407. var
  408. cquantize : my_cquantize_ptr;
  409. odither : ODITHER_MATRIX_PTR;
  410. i, j, nci : int;
  411. begin
  412. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  413. for i := 0 to pred(cinfo^.out_color_components) do
  414. begin
  415. nci := cquantize^.Ncolors[i]; { # of distinct values for this color }
  416. odither := NIL; { search for matching prior component }
  417. for j := 0 to pred(i) do
  418. begin
  419. if (nci = cquantize^.Ncolors[j]) then
  420. begin
  421. odither := cquantize^.odither[j];
  422. break;
  423. end;
  424. end;
  425. if (odither = NIL) then { need a new table? }
  426. odither := make_odither_array(cinfo, nci);
  427. cquantize^.odither[i] := odither;
  428. end;
  429. end;
  430. { Map some rows of pixels to the output colormapped representation. }
  431. {METHODDEF}
  432. procedure color_quantize (cinfo : j_decompress_ptr;
  433. input_buf : JSAMPARRAY;
  434. output_buf : JSAMPARRAY;
  435. num_rows : int);
  436. { General case, no dithering }
  437. var
  438. cquantize : my_cquantize_ptr;
  439. colorindex : JSAMPARRAY;
  440. pixcode, ci : int; {register}
  441. ptrin, ptrout : JSAMPLE_PTR; {register}
  442. row : int;
  443. col : JDIMENSION;
  444. width : JDIMENSION;
  445. nc : int; {register}
  446. begin
  447. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  448. colorindex := cquantize^.colorindex;
  449. width := cinfo^.output_width;
  450. nc := cinfo^.out_color_components;
  451. for row := 0 to pred(num_rows) do
  452. begin
  453. ptrin := JSAMPLE_PTR(input_buf^[row]);
  454. ptrout := JSAMPLE_PTR(output_buf^[row]);
  455. for col := pred(width) downto 0 do
  456. begin
  457. pixcode := 0;
  458. for ci := 0 to pred(nc) do
  459. begin
  460. Inc(pixcode, GETJSAMPLE(colorindex^[ci]^[GETJSAMPLE(ptrin^)]) );
  461. Inc(ptrin);
  462. end;
  463. ptrout^ := JSAMPLE (pixcode);
  464. Inc(ptrout);
  465. end;
  466. end;
  467. end;
  468. {METHODDEF}
  469. procedure color_quantize3 (cinfo : j_decompress_ptr;
  470. input_buf : JSAMPARRAY;
  471. output_buf : JSAMPARRAY;
  472. num_rows : int);
  473. { Fast path for out_color_components=3, no dithering }
  474. var
  475. cquantize : my_cquantize_ptr;
  476. pixcode : int; {register}
  477. ptrin, ptrout : JSAMPLE_PTR; {register}
  478. colorindex0 : JSAMPROW;
  479. colorindex1 : JSAMPROW;
  480. colorindex2 : JSAMPROW;
  481. row : int;
  482. col : JDIMENSION;
  483. width : JDIMENSION;
  484. begin
  485. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  486. colorindex0 := (cquantize^.colorindex)^[0];
  487. colorindex1 := (cquantize^.colorindex)^[1];
  488. colorindex2 := (cquantize^.colorindex)^[2];
  489. width := cinfo^.output_width;
  490. for row := 0 to pred(num_rows) do
  491. begin
  492. ptrin := JSAMPLE_PTR(input_buf^[row]);
  493. ptrout := JSAMPLE_PTR(output_buf^[row]);
  494. for col := pred(width) downto 0 do
  495. begin
  496. pixcode := GETJSAMPLE((colorindex0)^[GETJSAMPLE(ptrin^)]);
  497. Inc(ptrin);
  498. Inc( pixcode, GETJSAMPLE((colorindex1)^[GETJSAMPLE(ptrin^)]) );
  499. Inc(ptrin);
  500. Inc( pixcode, GETJSAMPLE((colorindex2)^[GETJSAMPLE(ptrin^)]) );
  501. Inc(ptrin);
  502. ptrout^ := JSAMPLE (pixcode);
  503. Inc(ptrout);
  504. end;
  505. end;
  506. end;
  507. {METHODDEF}
  508. procedure quantize_ord_dither (cinfo : j_decompress_ptr;
  509. input_buf : JSAMPARRAY;
  510. output_buf : JSAMPARRAY;
  511. num_rows : int);
  512. { General case, with ordered dithering }
  513. var
  514. cquantize : my_cquantize_ptr;
  515. input_ptr, {register}
  516. output_ptr : JSAMPLE_PTR; {register}
  517. colorindex_ci : JSAMPROW;
  518. dither : ^ODITHER_vector; { points to active row of dither matrix }
  519. row_index, col_index : int; { current indexes into dither matrix }
  520. nc : int;
  521. ci : int;
  522. row : int;
  523. col : JDIMENSION;
  524. width : JDIMENSION;
  525. var
  526. pad_offset : int;
  527. begin
  528. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  529. nc := cinfo^.out_color_components;
  530. width := cinfo^.output_width;
  531. { Nomssi: work around negative offset }
  532. if my_cquantize_ptr (cinfo^.cquantize)^.is_padded then
  533. pad_offset := MAXJSAMPLE
  534. else
  535. pad_offset := 0;
  536. for row := 0 to pred(num_rows) do
  537. begin
  538. { Initialize output values to 0 so can process components separately }
  539. jzero_far( {far} pointer(output_buf^[row]),
  540. size_t(width * SIZEOF(JSAMPLE)));
  541. row_index := cquantize^.row_index;
  542. for ci := 0 to pred(nc) do
  543. begin
  544. input_ptr := JSAMPLE_PTR(@ input_buf^[row]^[ci]);
  545. output_ptr := JSAMPLE_PTR(output_buf^[row]);
  546. colorindex_ci := cquantize^.colorindex^[ci];
  547. { Nomssi }
  548. Dec(JSAMPLE_PTR(colorindex_ci), pad_offset);
  549. dither := @(cquantize^.odither[ci]^[row_index]);
  550. col_index := 0;
  551. for col := pred(width) downto 0 do
  552. begin
  553. { Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
  554. select output value, accumulate into output code for this pixel.
  555. Range-limiting need not be done explicitly, as we have extended
  556. the colorindex table to produce the right answers for out-of-range
  557. inputs. The maximum dither is +- MAXJSAMPLE; this sets the
  558. required amount of padding. }
  559. Inc(output_ptr^,
  560. colorindex_ci^[GETJSAMPLE(input_ptr^)+ pad_offset +
  561. dither^[col_index]]);
  562. Inc(output_ptr);
  563. Inc(input_ptr, nc);
  564. col_index := (col_index + 1) and ODITHER_MASK;
  565. end;
  566. end;
  567. { Advance row index for next row }
  568. row_index := (row_index + 1) and ODITHER_MASK;
  569. cquantize^.row_index := row_index;
  570. end;
  571. end;
  572. {METHODDEF}
  573. procedure quantize3_ord_dither (cinfo : j_decompress_ptr;
  574. input_buf : JSAMPARRAY;
  575. output_buf : JSAMPARRAY;
  576. num_rows : int);
  577. { Fast path for out_color_components=3, with ordered dithering }
  578. var
  579. cquantize : my_cquantize_ptr;
  580. pixcode : int; {register}
  581. input_ptr : JSAMPLE_PTR; {register}
  582. output_ptr : JSAMPLE_PTR; {register}
  583. colorindex0 : JSAMPROW;
  584. colorindex1 : JSAMPROW;
  585. colorindex2 : JSAMPROW;
  586. dither0 : ^ODITHER_vector; { points to active row of dither matrix }
  587. dither1 : ^ODITHER_vector;
  588. dither2 : ^ODITHER_vector;
  589. row_index, col_index : int; { current indexes into dither matrix }
  590. row : int;
  591. col : JDIMENSION;
  592. width : JDIMENSION;
  593. var
  594. pad_offset : int;
  595. begin
  596. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  597. colorindex0 := (cquantize^.colorindex)^[0];
  598. colorindex1 := (cquantize^.colorindex)^[1];
  599. colorindex2 := (cquantize^.colorindex)^[2];
  600. width := cinfo^.output_width;
  601. { Nomssi: work around negative offset }
  602. if my_cquantize_ptr (cinfo^.cquantize)^.is_padded then
  603. pad_offset := MAXJSAMPLE
  604. else
  605. pad_offset := 0;
  606. Dec(JSAMPLE_PTR(colorindex0), pad_offset);
  607. Dec(JSAMPLE_PTR(colorindex1), pad_offset);
  608. Dec(JSAMPLE_PTR(colorindex2), pad_offset);
  609. for row := 0 to pred(num_rows) do
  610. begin
  611. row_index := cquantize^.row_index;
  612. input_ptr := JSAMPLE_PTR(input_buf^[row]);
  613. output_ptr := JSAMPLE_PTR(output_buf^[row]);
  614. dither0 := @(cquantize^.odither[0]^[row_index]);
  615. dither1 := @(cquantize^.odither[1]^[row_index]);
  616. dither2 := @(cquantize^.odither[2]^[row_index]);
  617. col_index := 0;
  618. for col := pred(width) downto 0 do
  619. begin
  620. pixcode := GETJSAMPLE(colorindex0^[GETJSAMPLE(input_ptr^) + pad_offset
  621. + dither0^[col_index]]);
  622. Inc(input_ptr);
  623. Inc(pixcode, GETJSAMPLE(colorindex1^[GETJSAMPLE(input_ptr^) + pad_offset
  624. + dither1^[col_index]]));
  625. Inc(input_ptr);
  626. Inc(pixcode, GETJSAMPLE(colorindex2^[GETJSAMPLE(input_ptr^) + pad_offset
  627. + dither2^[col_index]]));
  628. Inc(input_ptr);
  629. output_ptr^ := JSAMPLE (pixcode);
  630. Inc(output_ptr);
  631. col_index := (col_index + 1) and ODITHER_MASK;
  632. end;
  633. row_index := (row_index + 1) and ODITHER_MASK;
  634. cquantize^.row_index := row_index;
  635. end;
  636. end;
  637. {METHODDEF}
  638. procedure quantize_fs_dither (cinfo : j_decompress_ptr;
  639. input_buf : JSAMPARRAY;
  640. output_buf : JSAMPARRAY;
  641. num_rows : int);
  642. { General case, with Floyd-Steinberg dithering }
  643. var
  644. cquantize : my_cquantize_ptr;
  645. cur : LOCFSERROR; {register} { current error or pixel value }
  646. belowerr : LOCFSERROR; { error for pixel below cur }
  647. bpreverr : LOCFSERROR; { error for below/prev col }
  648. bnexterr : LOCFSERROR; { error for below/next col }
  649. delta : LOCFSERROR;
  650. prev_errorptr,
  651. errorptr : FSERRORPTR; {register} { => fserrors[] at column before current }
  652. input_ptr, {register}
  653. output_ptr : JSAMPLE_PTR; {register}
  654. colorindex_ci : JSAMPROW;
  655. colormap_ci : JSAMPROW;
  656. pixcode : int;
  657. nc : int;
  658. dir : int; { 1 for left-to-right, -1 for right-to-left }
  659. dirnc : int; { dir * nc }
  660. ci : int;
  661. row : int;
  662. col : JDIMENSION;
  663. width : JDIMENSION;
  664. range_limit : range_limit_table_ptr;
  665. begin
  666. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  667. nc := cinfo^.out_color_components;
  668. width := cinfo^.output_width;
  669. range_limit := cinfo^.sample_range_limit;
  670. for row := 0 to pred(num_rows) do
  671. begin
  672. { Initialize output values to 0 so can process components separately }
  673. jzero_far( (output_buf)^[row],
  674. size_t(width * SIZEOF(JSAMPLE)));
  675. for ci := 0 to pred(nc) do
  676. begin
  677. input_ptr := JSAMPLE_PTR(@ input_buf^[row]^[ci]);
  678. output_ptr := JSAMPLE_PTR(output_buf^[row]);
  679. errorptr := FSERRORPTR(cquantize^.fserrors[ci]); { => entry before first column }
  680. if (cquantize^.on_odd_row) then
  681. begin
  682. { work right to left in this row }
  683. Inc(input_ptr, (width-1) * JDIMENSION(nc)); { so point to rightmost pixel }
  684. Inc(output_ptr, width-1);
  685. dir := -1;
  686. dirnc := -nc;
  687. Inc(errorptr, (width+1)); { => entry after last column }
  688. end
  689. else
  690. begin
  691. { work left to right in this row }
  692. dir := 1;
  693. dirnc := nc;
  694. {errorptr := cquantize^.fserrors[ci];}
  695. end;
  696. colorindex_ci := cquantize^.colorindex^[ci];
  697. colormap_ci := (cquantize^.sv_colormap)^[ci];
  698. { Preset error values: no error propagated to first pixel from left }
  699. cur := 0;
  700. { and no error propagated to row below yet }
  701. belowerr := 0;
  702. bpreverr := 0;
  703. for col := pred(width) downto 0 do
  704. begin
  705. prev_errorptr := errorptr;
  706. Inc(errorptr, dir); { advance errorptr to current column }
  707. { cur holds the error propagated from the previous pixel on the
  708. current line. Add the error propagated from the previous line
  709. to form the complete error correction term for this pixel, and
  710. round the error term (which is expressed * 16) to an integer.
  711. RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
  712. for either sign of the error value.
  713. Note: errorptr points to *previous* column's array entry. }
  714. cur := (cur + errorptr^ + 8) div 16;
  715. { Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
  716. The maximum error is +- MAXJSAMPLE; this sets the required size
  717. of the range_limit array. }
  718. Inc( cur, GETJSAMPLE(input_ptr^));
  719. cur := GETJSAMPLE(range_limit^[cur]);
  720. { Select output value, accumulate into output code for this pixel }
  721. pixcode := GETJSAMPLE(colorindex_ci^[cur]);
  722. Inc(output_ptr^, JSAMPLE (pixcode));
  723. { Compute actual representation error at this pixel }
  724. { Note: we can do this even though we don't have the final }
  725. { pixel code, because the colormap is orthogonal. }
  726. Dec(cur, GETJSAMPLE(colormap_ci^[pixcode]));
  727. { Compute error fractions to be propagated to adjacent pixels.
  728. Add these into the running sums, and simultaneously shift the
  729. next-line error sums left by 1 column. }
  730. bnexterr := cur;
  731. delta := cur * 2;
  732. Inc(cur, delta); { form error * 3 }
  733. prev_errorptr^ := FSERROR (bpreverr + cur);
  734. Inc(cur, delta); { form error * 5 }
  735. bpreverr := belowerr + cur;
  736. belowerr := bnexterr;
  737. Inc(cur, delta); { form error * 7 }
  738. { At this point cur contains the 7/16 error value to be propagated
  739. to the next pixel on the current line, and all the errors for the
  740. next line have been shifted over. We are therefore ready to move on. }
  741. Inc(input_ptr, dirnc); { advance input ptr to next column }
  742. Inc(output_ptr, dir); { advance output ptr to next column }
  743. end;
  744. { Post-loop cleanup: we must unload the final error value into the
  745. final fserrors[] entry. Note we need not unload belowerr because
  746. it is for the dummy column before or after the actual array. }
  747. errorptr^ := FSERROR (bpreverr); { unload prev err into array }
  748. { Nomssi : ?? }
  749. end;
  750. cquantize^.on_odd_row := not cquantize^.on_odd_row;
  751. end;
  752. end;
  753. { Allocate workspace for Floyd-Steinberg errors. }
  754. {LOCAL}
  755. procedure alloc_fs_workspace (cinfo : j_decompress_ptr);
  756. var
  757. cquantize : my_cquantize_ptr;
  758. arraysize : size_t;
  759. i : int;
  760. begin
  761. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  762. arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR));
  763. for i := 0 to pred(cinfo^.out_color_components) do
  764. begin
  765. cquantize^.fserrors[i] := FS_ERROR_FIELD_PTR(
  766. cinfo^.mem^.alloc_large(j_common_ptr(cinfo), JPOOL_IMAGE, arraysize));
  767. end;
  768. end;
  769. { Initialize for one-pass color quantization. }
  770. {METHODDEF}
  771. procedure start_pass_1_quant (cinfo : j_decompress_ptr;
  772. is_pre_scan : boolean);
  773. var
  774. cquantize : my_cquantize_ptr;
  775. arraysize : size_t;
  776. i : int;
  777. begin
  778. cquantize := my_cquantize_ptr (cinfo^.cquantize);
  779. { Install my colormap. }
  780. cinfo^.colormap := cquantize^.sv_colormap;
  781. cinfo^.actual_number_of_colors := cquantize^.sv_actual;
  782. { Initialize for desired dithering mode. }
  783. case (cinfo^.dither_mode) of
  784. JDITHER_NONE:
  785. if (cinfo^.out_color_components = 3) then
  786. cquantize^.pub.color_quantize := color_quantize3
  787. else
  788. cquantize^.pub.color_quantize := color_quantize;
  789. JDITHER_ORDERED:
  790. begin
  791. if (cinfo^.out_color_components = 3) then
  792. cquantize^.pub.color_quantize := quantize3_ord_dither
  793. else
  794. cquantize^.pub.color_quantize := quantize_ord_dither;
  795. cquantize^.row_index := 0; { initialize state for ordered dither }
  796. { If user changed to ordered dither from another mode,
  797. we must recreate the color index table with padding.
  798. This will cost extra space, but probably isn't very likely. }
  799. if (not cquantize^.is_padded) then
  800. create_colorindex(cinfo);
  801. { Create ordered-dither tables if we didn't already. }
  802. if (cquantize^.odither[0] = NIL) then
  803. create_odither_tables(cinfo);
  804. end;
  805. JDITHER_FS:
  806. begin
  807. cquantize^.pub.color_quantize := quantize_fs_dither;
  808. cquantize^.on_odd_row := FALSE; { initialize state for F-S dither }
  809. { Allocate Floyd-Steinberg workspace if didn't already. }
  810. if (cquantize^.fserrors[0] = NIL) then
  811. alloc_fs_workspace(cinfo);
  812. { Initialize the propagated errors to zero. }
  813. arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR));
  814. for i := 0 to pred(cinfo^.out_color_components) do
  815. jzero_far({far} pointer( cquantize^.fserrors[i] ), arraysize);
  816. end;
  817. else
  818. ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
  819. end;
  820. end;
  821. { Finish up at the end of the pass. }
  822. {METHODDEF}
  823. procedure finish_pass_1_quant (cinfo : j_decompress_ptr);
  824. begin
  825. { no work in 1-pass case }
  826. end;
  827. { Switch to a new external colormap between output passes.
  828. Shouldn't get to this module! }
  829. {METHODDEF}
  830. procedure new_color_map_1_quant (cinfo : j_decompress_ptr);
  831. begin
  832. ERREXIT(j_common_ptr(cinfo), JERR_MODE_CHANGE);
  833. end;
  834. { Module initialization routine for 1-pass color quantization. }
  835. {GLOBAL}
  836. procedure jinit_1pass_quantizer (cinfo : j_decompress_ptr);
  837. var
  838. cquantize : my_cquantize_ptr;
  839. begin
  840. cquantize := my_cquantize_ptr(
  841. cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
  842. SIZEOF(my_cquantizer)));
  843. cinfo^.cquantize := jpeg_color_quantizer_ptr(cquantize);
  844. cquantize^.pub.start_pass := start_pass_1_quant;
  845. cquantize^.pub.finish_pass := finish_pass_1_quant;
  846. cquantize^.pub.new_color_map := new_color_map_1_quant;
  847. cquantize^.fserrors[0] := NIL; { Flag FS workspace not allocated }
  848. cquantize^.odither[0] := NIL; { Also flag odither arrays not allocated }
  849. { Make sure my internal arrays won't overflow }
  850. if (cinfo^.out_color_components > MAX_Q_COMPS) then
  851. ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
  852. { Make sure colormap indexes can be represented by JSAMPLEs }
  853. if (cinfo^.desired_number_of_colors > (MAXJSAMPLE+1)) then
  854. ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
  855. { Create the colormap and color index table. }
  856. create_colormap(cinfo);
  857. create_colorindex(cinfo);
  858. { Allocate Floyd-Steinberg workspace now if requested.
  859. We do this now since it is FAR storage and may affect the memory
  860. manager's space calculations. If the user changes to FS dither
  861. mode in a later pass, we will allocate the space then, and will
  862. possibly overrun the max_memory_to_use setting. }
  863. if (cinfo^.dither_mode = JDITHER_FS) then
  864. alloc_fs_workspace(cinfo);
  865. end;
  866. end.