INV_CMAP.C 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. /*
  14. * This software is copyrighted as noted below. It may be freely copied,
  15. * modified, and redistributed, provided that the copyright notice is
  16. * preserved on all copies.
  17. *
  18. * There is no warranty or other guarantee of fitness for this software,
  19. * it is provided solely "as is". Bug reports or fixes may be sent
  20. * to the author, who may or may not act on them as he desires.
  21. *
  22. * You may not include this software in a program or other software product
  23. * without supplying the source, or without informing the end-user that the
  24. * source is available for no extra charge.
  25. *
  26. * If you modify this software, you should include a notice giving the
  27. * name of the person performing the modification, the date of modification,
  28. * and the reason for such modification.
  29. */
  30. /*
  31. * inv_cmap.c - Compute an inverse colormap.
  32. *
  33. * Author: Spencer W. Thomas
  34. * EECS Dept.
  35. * University of Michigan
  36. * Date: Thu Sep 20 1990
  37. * Copyright (c) 1990, University of Michigan
  38. *
  39. * $Id: inv_cmap.c,v 3.0.1.1 90/11/29 15:09:43 spencer Exp $
  40. */
  41. #include <math.h>
  42. #include <stdio.h>
  43. /* Print some performance stats. */
  44. /* #define INSTRUMENT_IT */
  45. /* Track minimum and maximum in inv_cmap_2. */
  46. #define MINMAX_TRACK
  47. static int bcenter, gcenter, rcenter;
  48. static long gdist, rdist, cdist;
  49. static long cbinc, cginc, crinc;
  50. static unsigned long *gdp, *rdp, *cdp;
  51. static unsigned char *grgbp, *rrgbp, *crgbp;
  52. static gstride, rstride;
  53. static long x, xsqr, colormax;
  54. static int cindex;
  55. #ifdef INSTRUMENT_IT
  56. static long outercount = 0, innercount = 0;
  57. #endif
  58. /*****************************************************************
  59. * TAG( inv_cmap_2 )
  60. *
  61. * Compute an inverse colormap efficiently.
  62. * Inputs:
  63. * colors: Number of colors in the forward colormap.
  64. * colormap: The forward colormap.
  65. * bits: Number of quantization bits. The inverse
  66. * colormap will have (2^bits)^3 entries.
  67. * dist_buf: An array of (2^bits)^3 long integers to be
  68. * used as scratch space.
  69. * Outputs:
  70. * rgbmap: The output inverse colormap. The entry
  71. * rgbmap[(r<<(2*bits)) + (g<<bits) + b]
  72. * is the colormap entry that is closest to the
  73. * (quantized) color (r,g,b).
  74. * Assumptions:
  75. * Quantization is performed by right shift (low order bits are
  76. * truncated). Thus, the distance to a quantized color is
  77. * actually measured to the color at the center of the cell
  78. * (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
  79. * Algorithm:
  80. * Uses a "distance buffer" algorithm:
  81. * The distance from each representative in the forward color map
  82. * to each point in the rgb space is computed. If it is less
  83. * than the distance currently stored in dist_buf, then the
  84. * corresponding entry in rgbmap is replaced with the current
  85. * representative (and the dist_buf entry is replaced with the
  86. * new distance).
  87. *
  88. * The distance computation uses an efficient incremental formulation.
  89. *
  90. * Distances are computed "outward" from each color. If the
  91. * colors are evenly distributed in color space, the expected
  92. * number of cells visited for color I is N^3/I.
  93. * Thus, the complexity of the algorithm is O(log(K) N^3),
  94. * where K = colors, and N = 2^bits.
  95. */
  96. /*
  97. * Here's the idea: scan from the "center" of each cell "out"
  98. * until we hit the "edge" of the cell -- that is, the point
  99. * at which some other color is closer -- and stop. In 1-D,
  100. * this is simple:
  101. * for i := here to max do
  102. * if closer then buffer[i] = this color
  103. * else break
  104. * repeat above loop with i := here-1 to min by -1
  105. *
  106. * In 2-D, it's trickier, because along a "scan-line", the
  107. * region might start "after" the "center" point. A picture
  108. * might clarify:
  109. * | ...
  110. * | ... .
  111. * ... .
  112. * ... | .
  113. * . + .
  114. * . .
  115. * . .
  116. * .........
  117. *
  118. * The + marks the "center" of the above region. On the top 2
  119. * lines, the region "begins" to the right of the "center".
  120. *
  121. * Thus, we need a loop like this:
  122. * detect := false
  123. * for i := here to max do
  124. * if closer then
  125. * buffer[..., i] := this color
  126. * if !detect then
  127. * here = i
  128. * detect = true
  129. * else
  130. * if detect then
  131. * break
  132. *
  133. * Repeat the above loop with i := here-1 to min by -1. Note that
  134. * the "detect" value should not be reinitialized. If it was
  135. * "true", and center is not inside the cell, then none of the
  136. * cell lies to the left and this loop should exit
  137. * immediately.
  138. *
  139. * The outer loops are similar, except that the "closer" test
  140. * is replaced by a call to the "next in" loop; its "detect"
  141. * value serves as the test. (No assignment to the buffer is
  142. * done, either.)
  143. *
  144. * Each time an outer loop starts, the "here", "min", and
  145. * "max" values of the next inner loop should be
  146. * re-initialized to the center of the cell, 0, and cube size,
  147. * respectively. Otherwise, these values will carry over from
  148. * one "call" to the inner loop to the next. This tracks the
  149. * edges of the cell and minimizes the number of
  150. * "unproductive" comparisons that must be made.
  151. *
  152. * Finally, the inner-most loop can have the "if !detect"
  153. * optimized out of it by splitting it into two loops: one
  154. * that finds the first color value on the scan line that is
  155. * in this cell, and a second that fills the cell until
  156. * another one is closer:
  157. * if !detect then {needed for "down" loop}
  158. * for i := here to max do
  159. * if closer then
  160. * buffer[..., i] := this color
  161. * detect := true
  162. * break
  163. * for i := i+1 to max do
  164. * if closer then
  165. * buffer[..., i] := this color
  166. * else
  167. * break
  168. *
  169. * In this implementation, each level will require the
  170. * following variables. Variables labelled (l) are local to each
  171. * procedure. The ? should be replaced with r, g, or b:
  172. * cdist: The distance at the starting point.
  173. * ?center: The value of this component of the color
  174. * c?inc: The initial increment at the ?center position.
  175. * ?stride: The amount to add to the buffer
  176. * pointers (dp and rgbp) to get to the
  177. * "next row".
  178. * min(l): The "low edge" of the cell, init to 0
  179. * max(l): The "high edge" of the cell, init to
  180. * colormax-1
  181. * detect(l): True if this row has changed some
  182. * buffer entries.
  183. * i(l): The index for this row.
  184. * ?xx: The accumulated increment value.
  185. *
  186. * here(l): The starting index for this color. The
  187. * following variables are associated with here,
  188. * in the sense that they must be updated if here
  189. * is changed.
  190. * ?dist: The current distance for this level. The
  191. * value of dist from the previous level (g or r,
  192. * for level b or g) initializes dist on this
  193. * level. Thus gdist is associated with here(b)).
  194. * ?inc: The initial increment for the row.
  195. * ?dp: Pointer into the distance buffer. The value
  196. * from the previous level initializes this level.
  197. * ?rgbp: Pointer into the rgb buffer. The value
  198. * from the previous level initializes this level.
  199. *
  200. * The blue and green levels modify 'here-associated' variables (dp,
  201. * rgbp, dist) on the green and red levels, respectively, when here is
  202. * changed.
  203. */
  204. void
  205. inv_cmap_2( colors, colormap, bits, dist_buf, rgbmap )
  206. int colors, bits;
  207. unsigned char *colormap, *rgbmap;
  208. unsigned long *dist_buf;
  209. {
  210. int nbits = 6 - bits;
  211. colormax = 1 << bits;
  212. x = 1 << nbits;
  213. xsqr = 1 << (2 * nbits);
  214. /* Compute "strides" for accessing the arrays. */
  215. gstride = colormax;
  216. rstride = colormax * colormax;
  217. #ifdef INSTRUMENT_IT
  218. outercount = 0;
  219. innercount = 0;
  220. #endif
  221. maxfill( dist_buf, colormax );
  222. for ( cindex = 0; cindex < colors; cindex++ )
  223. {
  224. /*
  225. * Distance formula is
  226. * (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
  227. *
  228. * Because of quantization, we will measure from the center of
  229. * each quantized "cube", so blue distance is
  230. * (blue + x/2 - map[2])^2,
  231. * where x = 2^(8 - bits).
  232. * The step size is x, so the blue increment is
  233. * 2*x*blue - 2*x*map[2] + 2*x^2
  234. *
  235. * Now, b in the code below is actually blue/x, so our
  236. * increment will be 2*(b*x^2 + x^2 - x*map[2]). For
  237. * efficiency, we will maintain this quantity in a separate variable
  238. * that will be updated incrementally by adding 2*x^2 each time.
  239. */
  240. /* The initial position is the cell containing the colormap
  241. * entry. We get this by quantizing the colormap values.
  242. */
  243. rcenter = colormap[cindex*3+0] >> nbits;
  244. gcenter = colormap[cindex*3+1] >> nbits;
  245. bcenter = colormap[cindex*3+2] >> nbits;
  246. rdist = colormap[cindex*3+0] - (rcenter * x + x/2);
  247. gdist = colormap[cindex*3+1] - (gcenter * x + x/2);
  248. cdist = colormap[cindex*3+2] - (bcenter * x + x/2);
  249. cdist = rdist*rdist + gdist*gdist + cdist*cdist;
  250. crinc = 2 * ((rcenter + 1) * xsqr - (colormap[0+3*cindex] * x));
  251. cginc = 2 * ((gcenter + 1) * xsqr - (colormap[1+3*cindex] * x));
  252. cbinc = 2 * ((bcenter + 1) * xsqr - (colormap[2+3*cindex] * x));
  253. /* Array starting points. */
  254. cdp = dist_buf + rcenter * rstride + gcenter * gstride + bcenter;
  255. crgbp = rgbmap + rcenter * rstride + gcenter * gstride + bcenter;
  256. (void)redloop();
  257. }
  258. #ifdef INSTRUMENT_IT
  259. fprintf( stderr, "K = %d, N = %d, outer count = %ld, inner count = %ld\n",
  260. colors, colormax, outercount, innercount );
  261. #endif
  262. }
  263. /* redloop -- loop up and down from red center. */
  264. int
  265. redloop()
  266. {
  267. int detect;
  268. int r, i = cindex;
  269. int first;
  270. long txsqr = xsqr + xsqr;
  271. static int here, min, max;
  272. static long rxx;
  273. detect = 0;
  274. /* Basic loop up. */
  275. for ( r = rcenter, rdist = cdist, rxx = crinc,
  276. rdp = cdp, rrgbp = crgbp, first = 1;
  277. r < colormax;
  278. r++, rdp += rstride, rrgbp += rstride,
  279. rdist += rxx, rxx += txsqr, first = 0 )
  280. {
  281. if ( greenloop( first ) )
  282. detect = 1;
  283. else if ( detect )
  284. break;
  285. }
  286. /* Basic loop down. */
  287. for ( r = rcenter - 1, rxx = crinc - txsqr, rdist = cdist - rxx,
  288. rdp = cdp - rstride, rrgbp = crgbp - rstride, first = 1;
  289. r >= 0;
  290. r--, rdp -= rstride, rrgbp -= rstride,
  291. rxx -= txsqr, rdist -= rxx, first = 0 )
  292. {
  293. if ( greenloop( first ) )
  294. detect = 1;
  295. else if ( detect )
  296. break;
  297. }
  298. return detect;
  299. }
  300. /* greenloop -- loop up and down from green center. */
  301. int
  302. greenloop( restart )
  303. {
  304. int detect;
  305. int g, i = cindex;
  306. int first;
  307. long txsqr = xsqr + xsqr;
  308. static int here, min, max;
  309. #ifdef MINMAX_TRACK
  310. static int prevmax, prevmin;
  311. int thismax, thismin;
  312. #endif
  313. static long ginc, gxx, gcdist; /* "gc" variables maintain correct */
  314. static unsigned long *gcdp; /* values for bcenter position, */
  315. static unsigned char *gcrgbp; /* despite modifications by blueloop */
  316. /* to gdist, gdp, grgbp. */
  317. if ( restart )
  318. {
  319. here = gcenter;
  320. min = 0;
  321. max = colormax - 1;
  322. ginc = cginc;
  323. #ifdef MINMAX_TRACK
  324. prevmax = 0;
  325. prevmin = colormax;
  326. #endif
  327. }
  328. #ifdef MINMAX_TRACK
  329. thismin = min;
  330. thismax = max;
  331. #endif
  332. detect = 0;
  333. /* Basic loop up. */
  334. for ( g = here, gcdist = gdist = rdist, gxx = ginc,
  335. gcdp = gdp = rdp, gcrgbp = grgbp = rrgbp, first = 1;
  336. g <= max;
  337. g++, gdp += gstride, gcdp += gstride, grgbp += gstride, gcrgbp += gstride,
  338. gdist += gxx, gcdist += gxx, gxx += txsqr, first = 0 )
  339. {
  340. if ( blueloop( first ) )
  341. {
  342. if ( !detect )
  343. {
  344. /* Remember here and associated data! */
  345. if ( g > here )
  346. {
  347. here = g;
  348. rdp = gcdp;
  349. rrgbp = gcrgbp;
  350. rdist = gcdist;
  351. ginc = gxx;
  352. #ifdef MINMAX_TRACK
  353. thismin = here;
  354. #endif
  355. }
  356. detect = 1;
  357. }
  358. }
  359. else if ( detect )
  360. {
  361. #ifdef MINMAX_TRACK
  362. thismax = g - 1;
  363. #endif
  364. break;
  365. }
  366. }
  367. /* Basic loop down. */
  368. for ( g = here - 1, gxx = ginc - txsqr, gcdist = gdist = rdist - gxx,
  369. gcdp = gdp = rdp - gstride, gcrgbp = grgbp = rrgbp - gstride,
  370. first = 1;
  371. g >= min;
  372. g--, gdp -= gstride, gcdp -= gstride, grgbp -= gstride, gcrgbp -= gstride,
  373. gxx -= txsqr, gdist -= gxx, gcdist -= gxx, first = 0 )
  374. {
  375. if ( blueloop( first ) )
  376. {
  377. if ( !detect )
  378. {
  379. /* Remember here! */
  380. here = g;
  381. rdp = gcdp;
  382. rrgbp = gcrgbp;
  383. rdist = gcdist;
  384. ginc = gxx;
  385. #ifdef MINMAX_TRACK
  386. thismax = here;
  387. #endif
  388. detect = 1;
  389. }
  390. }
  391. else if ( detect )
  392. {
  393. #ifdef MINMAX_TRACK
  394. thismin = g + 1;
  395. #endif
  396. break;
  397. }
  398. }
  399. #ifdef MINMAX_TRACK
  400. /* If we saw something, update the edge trackers. For now, only
  401. * tracks edges that are "shrinking" (min increasing, max
  402. * decreasing.
  403. */
  404. if ( detect )
  405. {
  406. if ( thismax < prevmax )
  407. max = thismax;
  408. prevmax = thismax;
  409. if ( thismin > prevmin )
  410. min = thismin;
  411. prevmin = thismin;
  412. }
  413. #endif
  414. return detect;
  415. }
  416. /* blueloop -- loop up and down from blue center. */
  417. int
  418. blueloop( restart )
  419. {
  420. int detect;
  421. register unsigned long *dp;
  422. register unsigned char *rgbp;
  423. register long bdist, bxx;
  424. register int b, i = cindex;
  425. register long txsqr = xsqr + xsqr;
  426. register int lim;
  427. static int here, min, max;
  428. #ifdef MINMAX_TRACK
  429. static int prevmin, prevmax;
  430. int thismin, thismax;
  431. #endif /* MINMAX_TRACK */
  432. static long binc;
  433. if ( restart )
  434. {
  435. here = bcenter;
  436. min = 0;
  437. max = colormax - 1;
  438. binc = cbinc;
  439. #ifdef MINMAX_TRACK
  440. prevmin = colormax;
  441. prevmax = 0;
  442. #endif /* MINMAX_TRACK */
  443. }
  444. detect = 0;
  445. #ifdef MINMAX_TRACK
  446. thismin = min;
  447. thismax = max;
  448. #endif
  449. /* Basic loop up. */
  450. /* First loop just finds first applicable cell. */
  451. for ( b = here, bdist = gdist, bxx = binc, dp = gdp, rgbp = grgbp, lim = max;
  452. b <= lim;
  453. b++, dp++, rgbp++,
  454. bdist += bxx, bxx += txsqr )
  455. {
  456. #ifdef INSTRUMENT_IT
  457. outercount++;
  458. #endif
  459. if ( *dp > bdist )
  460. {
  461. /* Remember new 'here' and associated data! */
  462. if ( b > here )
  463. {
  464. here = b;
  465. gdp = dp;
  466. grgbp = rgbp;
  467. gdist = bdist;
  468. binc = bxx;
  469. #ifdef MINMAX_TRACK
  470. thismin = here;
  471. #endif
  472. }
  473. detect = 1;
  474. #ifdef INSTRUMENT_IT
  475. outercount--;
  476. #endif
  477. break;
  478. }
  479. }
  480. /* Second loop fills in a run of closer cells. */
  481. for ( ;
  482. b <= lim;
  483. b++, dp++, rgbp++,
  484. bdist += bxx, bxx += txsqr )
  485. {
  486. #ifdef INSTRUMENT_IT
  487. outercount++;
  488. #endif
  489. if ( *dp > bdist )
  490. {
  491. #ifdef INSTRUMENT_IT
  492. innercount++;
  493. #endif
  494. *dp = bdist;
  495. *rgbp = i;
  496. }
  497. else
  498. {
  499. #ifdef MINMAX_TRACK
  500. thismax = b - 1;
  501. #endif
  502. break;
  503. }
  504. }
  505. /* Basic loop down. */
  506. /* Do initializations here, since the 'find' loop might not get
  507. * executed.
  508. */
  509. lim = min;
  510. b = here - 1;
  511. bxx = binc - txsqr;
  512. bdist = gdist - bxx;
  513. dp = gdp - 1;
  514. rgbp = grgbp - 1;
  515. /* The 'find' loop is executed only if we didn't already find
  516. * something.
  517. */
  518. if ( !detect )
  519. for ( ;
  520. b >= lim;
  521. b--, dp--, rgbp--,
  522. bxx -= txsqr, bdist -= bxx )
  523. {
  524. #ifdef INSTRUMENT_IT
  525. outercount++;
  526. #endif
  527. if ( *dp > bdist )
  528. {
  529. /* Remember here! */
  530. /* No test for b against here necessary because b <
  531. * here by definition.
  532. */
  533. here = b;
  534. gdp = dp;
  535. grgbp = rgbp;
  536. gdist = bdist;
  537. binc = bxx;
  538. #ifdef MINMAX_TRACK
  539. thismax = here;
  540. #endif
  541. detect = 1;
  542. #ifdef INSTRUMENT_IT
  543. outercount--;
  544. #endif
  545. break;
  546. }
  547. }
  548. /* The 'update' loop. */
  549. for ( ;
  550. b >= lim;
  551. b--, dp--, rgbp--,
  552. bxx -= txsqr, bdist -= bxx )
  553. {
  554. #ifdef INSTRUMENT_IT
  555. outercount++;
  556. #endif
  557. if ( *dp > bdist )
  558. {
  559. #ifdef INSTRUMENT_IT
  560. innercount++;
  561. #endif
  562. *dp = bdist;
  563. *rgbp = i;
  564. }
  565. else
  566. {
  567. #ifdef MINMAX_TRACK
  568. thismin = b + 1;
  569. #endif
  570. break;
  571. }
  572. }
  573. /* If we saw something, update the edge trackers. */
  574. #ifdef MINMAX_TRACK
  575. if ( detect )
  576. {
  577. /* Only tracks edges that are "shrinking" (min increasing, max
  578. * decreasing.
  579. */
  580. if ( thismax < prevmax )
  581. max = thismax;
  582. if ( thismin > prevmin )
  583. min = thismin;
  584. /* Remember the min and max values. */
  585. prevmax = thismax;
  586. prevmin = thismin;
  587. }
  588. #endif /* MINMAX_TRACK */
  589. return detect;
  590. }
  591. maxfill( buffer, side )
  592. unsigned long *buffer;
  593. long side;
  594. {
  595. register unsigned long maxv = ~0L;
  596. register long i;
  597. register unsigned long *bp;
  598. for ( i = colormax * colormax * colormax, bp = buffer;
  599. i > 0;
  600. i--, bp++ )
  601. *bp = maxv;
  602. }
  603. /*****************************************************************
  604. * TAG( inv_cmap_1 )
  605. *
  606. * Compute an inverse colormap efficiently.
  607. * Inputs:
  608. * colors: Number of colors in the forward colormap.
  609. * colormap: The forward colormap.
  610. * bits: Number of quantization bits. The inverse
  611. * colormap will have (2^bits)^3 entries.
  612. * dist_buf: An array of (2^bits)^3 long integers to be
  613. * used as scratch space.
  614. * Outputs:
  615. * rgbmap: The output inverse colormap. The entry
  616. * rgbmap[(r<<(2*bits)) + (g<<bits) + b]
  617. * is the colormap entry that is closest to the
  618. * (quantized) color (r,g,b).
  619. * Assumptions:
  620. * Quantization is performed by right shift (low order bits are
  621. * truncated). Thus, the distance to a quantized color is
  622. * actually measured to the color at the center of the cell
  623. * (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
  624. * Algorithm:
  625. * Uses a "distance buffer" algorithm:
  626. * The distance from each representative in the forward color map
  627. * to each point in the rgb space is computed. If it is less
  628. * than the distance currently stored in dist_buf, then the
  629. * corresponding entry in rgbmap is replaced with the current
  630. * representative (and the dist_buf entry is replaced with the
  631. * new distance).
  632. *
  633. * The distance computation uses an efficient incremental formulation.
  634. *
  635. * Right now, distances are computed for all entries in the rgb
  636. * space. Thus, the complexity of the algorithm is O(K N^3),
  637. * where K = colors, and N = 2^bits.
  638. */
  639. void
  640. inv_cmap_1( colors, colormap, bits, dist_buf, rgbmap )
  641. int colors, bits;
  642. unsigned char *colormap, *rgbmap;
  643. unsigned long *dist_buf;
  644. {
  645. register unsigned long *dp;
  646. register unsigned char *rgbp;
  647. register long bdist, bxx;
  648. register int b, i;
  649. int nbits = 8 - bits;
  650. register int colormax = 1 << bits;
  651. register long xsqr = 1 << (2 * nbits);
  652. int x = 1 << nbits;
  653. int rinc, ginc, binc, r, g;
  654. long rdist, gdist, rxx, gxx;
  655. for ( i = 0; i < colors; i++ )
  656. {
  657. /*
  658. * Distance formula is
  659. * (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
  660. *
  661. * Because of quantization, we will measure from the center of
  662. * each quantized "cube", so blue distance is
  663. * (blue + x/2 - map[2])^2,
  664. * where x = 2^(8 - bits).
  665. * The step size is x, so the blue increment is
  666. * 2*x*blue - 2*x*map[2] + 2*x^2
  667. *
  668. * Now, b in the code below is actually blue/x, so our
  669. * increment will be 2*x*x*b + (2*x^2 - 2*x*map[2]). For
  670. * efficiency, we will maintain this quantity in a separate variable
  671. * that will be updated incrementally by adding 2*x^2 each time.
  672. */
  673. rdist = colormap[0+3*i] - x/2;
  674. gdist = colormap[1+3*i] - x/2;
  675. bdist = colormap[2+3*i] - x/2;
  676. rdist = rdist*rdist + gdist*gdist + bdist*bdist;
  677. rinc = 2 * (xsqr - (colormap[0+3*i] << nbits));
  678. ginc = 2 * (xsqr - (colormap[1+3*i] << nbits));
  679. binc = 2 * (xsqr - (colormap[2+3*i] << nbits));
  680. dp = dist_buf;
  681. rgbp = rgbmap;
  682. for ( r = 0, rxx = rinc;
  683. r < colormax;
  684. rdist += rxx, r++, rxx += xsqr + xsqr )
  685. for ( g = 0, gdist = rdist, gxx = ginc;
  686. g < colormax;
  687. gdist += gxx, g++, gxx += xsqr + xsqr )
  688. for ( b = 0, bdist = gdist, bxx = binc;
  689. b < colormax;
  690. bdist += bxx, b++, dp++, rgbp++,
  691. bxx += xsqr + xsqr )
  692. {
  693. #ifdef INSTRUMENT_IT
  694. outercount++;
  695. #endif
  696. if ( i == 0 || *dp > bdist )
  697. {
  698. #ifdef INSTRUMENT_IT
  699. innercount++;
  700. #endif
  701. *dp = bdist;
  702. *rgbp = i;
  703. }
  704. }
  705. }
  706. #ifdef INSTRUMENT_IT
  707. fprintf( stderr, "K = %d, N = %d, outer count = %ld, inner count = %ld\n",
  708. colors, colormax, outercount, innercount );
  709. #endif
  710. }
  711.