Leaked source code of windows server 2003
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.

1002 lines
30 KiB

  1. /*****************************************************************************
  2. *
  3. * Inverse color map code, from Graphics Gems II.
  4. *
  5. * this code builds a inverse map table, used for color mapping a
  6. * hi color (bpp > 8) image down to 4bpp or 8bpp
  7. *
  8. * a inverse table is a 32K table that mapps a RGB 555 value (a WORD) to
  9. * a palette index (a BYTE)
  10. *
  11. * public functions:
  12. * MakeITable - makes a inverse table to any palette
  13. *
  14. * non-public functions:
  15. * inv_cmap - work horse for MakeITable
  16. * MakeITableVGA - makes a inverse table to the VGA colors
  17. * MakeITable256 - makes a inverse table to a uniform 6 level palette
  18. *
  19. * Created: Feb 20 1994, ToddLa
  20. *
  21. * Copyright (c) 1994-1999 Microsoft Corporation
  22. *****************************************************************************/
  23. #include "precomp.hxx"
  24. #ifdef WIN32
  25. #define _huge
  26. #undef GlobalAllocPtr
  27. #undef GlobalFreePtr
  28. #define GlobalAllocPtr(f, cb) (LPVOID)GlobalAlloc(((f) & ~GMEM_MOVEABLE) | GMEM_FIXED, cb)
  29. #define GlobalFreePtr(p) GlobalFree((HGLOBAL)(p))
  30. #endif
  31. typedef DWORD _huge *PDIST;
  32. typedef BYTE FAR *PIMAP;
  33. typedef struct {BYTE r,g,b,x;} RGBX;
  34. void inv_cmap( int colors, RGBX FAR *colormap, int bits,
  35. PDIST dist_buf, PIMAP rgbmap );
  36. BOOL MakeITableMono(PIMAP lpITable);
  37. BOOL MakeITable256(PIMAP lpITable);
  38. BOOL MakeITableVGA(PIMAP lpITable);
  39. BOOL MakeITableDEF(PIMAP lpITable);
  40. PBYTE gpDefITable = NULL;
  41. /*****************************************************************************
  42. *
  43. * MakeITable
  44. *
  45. * build a 32k color inverse table to a palette
  46. *
  47. * lpITable points to a 32K table to hold inverse table
  48. * prgb points to the palette RGBs to build table from.
  49. * nColors number of RGBs
  50. *
  51. * if prgb is NULL build a special inverse table, to a fixed color table
  52. *
  53. * nColors = 2 build to mono colors (black,white)
  54. * nColors = 16 build to VGA colors.
  55. * nColors = 20 build to GDI DEFAULT_PALETTE
  56. * nColors = 216 build to 6*6*6 colors.
  57. *
  58. *****************************************************************************/
  59. BOOL MakeITable(PIMAP lpITable, RGBX FAR *prgb, int nColors)
  60. {
  61. PDIST lpDistBuf;
  62. PIMAP iTable = lpITable;
  63. //
  64. // handle special color tables.
  65. //
  66. if (prgb == NULL)
  67. {
  68. switch (nColors)
  69. {
  70. case 2:
  71. return MakeITableMono(lpITable);
  72. case 16:
  73. return MakeITableVGA(lpITable);
  74. case 20:
  75. return MakeITableDEF(lpITable);
  76. case 256:
  77. return MakeITable256(lpITable);
  78. default:
  79. return FALSE;
  80. }
  81. }
  82. //
  83. // We need to grab the global palette semaphore here
  84. // because inv_cmap is not thread-safe (it uses all
  85. // kinds of global variables)
  86. //
  87. BOOL result = FALSE;
  88. SEMOBJ semo(ghsemPalette);
  89. //
  90. // Check if palette is default palette. If it is, use the
  91. // cached default palette iTable. Create cache as appropriate.
  92. //
  93. if(nColors >= 20)
  94. {
  95. int i;
  96. ULONG * pulDef = (ULONG *) logDefaultPal.palPalEntry;
  97. ULONG * pulSrc = (ULONG *) prgb;
  98. for(i = 0; i < nColors; i++)
  99. if(pulSrc[i] != pulDef[i%20])
  100. break;
  101. if(i == nColors)
  102. {
  103. if(gpDefITable != NULL)
  104. {
  105. RtlCopyMemory(lpITable, gpDefITable, 32768);
  106. return TRUE;
  107. }
  108. iTable = (PBYTE)PALLOCNOZ(32768,'tidG');
  109. if(iTable == NULL)
  110. iTable = lpITable;
  111. nColors = 20;
  112. }
  113. }
  114. //
  115. // not a special table
  116. //
  117. lpDistBuf = (PDIST)PALLOCNOZ(32768l * sizeof(DWORD),'pmtG');
  118. if (lpDistBuf != NULL)
  119. {
  120. inv_cmap(nColors,prgb,5,lpDistBuf, iTable);
  121. VFREEMEM(lpDistBuf);
  122. result = TRUE;
  123. if(iTable != lpITable)
  124. {
  125. RtlCopyMemory(lpITable, iTable, 32768);
  126. gpDefITable = iTable;
  127. }
  128. }
  129. else
  130. {
  131. if(iTable != lpITable)
  132. VFREEMEM(iTable);
  133. }
  134. return result;
  135. }
  136. /*****************************************************************************
  137. *
  138. * MakeITable256
  139. *
  140. * build a 32k color inverse table to a 3-3-2 palette
  141. *
  142. *****************************************************************************/
  143. BOOL MakeITable256(PIMAP lpITable)
  144. {
  145. PIMAP pb;
  146. int r,g,b;
  147. pb = lpITable;
  148. for (r=0;r<32;r++)
  149. for (g=0;g<32;g++)
  150. for (b=0;b<32;b++)
  151. *pb++ = (((r & 0x1c) << 3)| (g & 0x1c) | ((b & 0x18) >> 3));
  152. return TRUE;
  153. }
  154. //;-----------------------------------------------------------------------------
  155. //; vga_map
  156. //; ;
  157. //; Subdividing the RGB color cube twice along each axis yields 64 smaller ;
  158. //; cubes. A maximum of three VGA colors, and often only one VGA color, ;
  159. //; match (Euclidean distance) into each of the subdivided cubes. Therefore, ;
  160. //; this adaptive Eudclidean match is must faster than the traditional ;
  161. //; Euclidean match. ;
  162. //; ;
  163. //; Note: This table was built according to the VGA palette. The ;
  164. //; indices it returns will not be appropriate for all devices. Use a ;
  165. //; VgaTranslateMap to produce the final physical color index. ;
  166. //; (Example: GDI has indices 7 and 8 reversed. To use this code in GDI, ;
  167. //; enable the VgaTranslateMap and swap indices 7 and 8.) ;
  168. //; ;
  169. //; The index to this map is computed as follows given a 24-bit RGB. ;
  170. //; ;
  171. //; index = ((Red & 0xC0) >> 2) | ;
  172. //; ((Green & 0xC0) >> 4) | ;
  173. //; ((Blue & 0xC0) >> 6); ;
  174. //; ;
  175. //; Each entry is a word made up of four nibbles. The first nibble always ;
  176. //; contains a valid GDI VGA color index. The second and third nibbles ;
  177. //; contain valid GDI VGA color indices if they are non-zero. ;
  178. //; The fourth nibble is an optimization for sub-cubes 42 and 63. ;
  179. //; ;
  180. //; History: ;
  181. //; 23-February-1994 -by- Raymond E. Endres [rayen] ;
  182. //; Wrote it. ;
  183. //;-----------------------------------------------------------------------------
  184. static WORD vga_map[] = {
  185. 0x0000, // Index 0 r=0 g=0 b=0
  186. 0x0004, // r=1 g=0 b=0
  187. 0x0004, // r=2 g=0 b=0
  188. 0x000C, // r=3 g=0 b=0
  189. 0x0002, // r=0 g=1 b=0
  190. 0x0006, // r=1 g=1 b=0
  191. 0x0006, // r=2 g=1 b=0
  192. 0x00C6, // r=3 g=1 b=0
  193. 0x0002, // Index 8 r=0 g=2 b=0
  194. 0x0006, // r=1 g=2 b=0
  195. 0x0006, // r=2 g=2 b=0
  196. 0x00E6, // r=3 g=2 b=0
  197. 0x000A, // r=0 g=3 b=0
  198. 0x00A6, // r=1 g=3 b=0
  199. 0x00E6, // r=2 g=3 b=0
  200. 0x000E, // r=3 g=3 b=0
  201. 0x0001, // Index 16 r=0 g=0 b=1
  202. 0x0005, // r=1 g=0 b=1
  203. 0x0005, // r=2 g=0 b=1
  204. 0x00C5, // r=3 g=0 b=1
  205. 0x0003, // r=0 g=1 b=1
  206. 0x0008, // r=1 g=1 b=1
  207. 0x0008, // r=2 g=1 b=1
  208. 0x0C78, // r=3 g=1 b=1
  209. 0x0003, // Index 24 r=0 g=2 b=1
  210. 0x0008, // r=1 g=2 b=1
  211. 0x0078, // r=2 g=2 b=1
  212. 0x0E78, // r=3 g=2 b=1
  213. 0x00A3, // r=0 g=3 b=1
  214. 0x0A78, // r=1 g=3 b=1
  215. 0x0E78, // r=2 g=3 b=1
  216. 0x0E78, // r=3 g=3 b=1
  217. 0x0001, // Index 32 r=0 g=0 b=2
  218. 0x0005, // r=1 g=0 b=2
  219. 0x0005, // r=2 g=0 b=2
  220. 0x00D5, // r=3 g=0 b=2
  221. 0x0003, // r=0 g=1 b=2
  222. 0x0008, // r=1 g=1 b=2
  223. 0x0078, // r=2 g=1 b=2
  224. 0x0D78, // r=3 g=1 b=2
  225. 0x0003, // Index 40 r=0 g=2 b=2
  226. 0x0078, // r=1 g=2 b=2
  227. 0x0078, // r=2 g=2 b=2 1
  228. 0x0078, // r=3 g=2 b=2
  229. 0x00B3, // r=0 g=3 b=2
  230. 0x0B78, // r=1 g=3 b=2
  231. 0x0078, // r=2 g=3 b=2
  232. 0x00F7, // r=3 g=3 b=2
  233. 0x0009, // Index 48 r=0 g=0 b=3
  234. 0x0095, // r=1 g=0 b=3
  235. 0x00D5, // r=2 g=0 b=3
  236. 0x000D, // r=3 g=0 b=3
  237. 0x0093, // r=0 g=1 b=3
  238. 0x0978, // r=1 g=1 b=3
  239. 0x0D78, // r=2 g=1 b=3
  240. 0x0D78, // r=3 g=1 b=3
  241. 0x00B3, // Index 56 r=0 g=2 b=3
  242. 0x0B78, // r=1 g=2 b=3
  243. 0x0078, // r=2 g=2 b=3
  244. 0x00F7, // r=3 g=2 b=3
  245. 0x000B, // r=0 g=3 b=3
  246. 0x0B78, // r=1 g=3 b=3
  247. 0x00F7, // r=2 g=3 b=3
  248. 0x00F7 // r=3 g=3 b=3 1
  249. };
  250. static RGBX VGAColors[] = {
  251. 00, 00, 00, 00,
  252. 16, 00, 00, 00,
  253. 00, 16, 00, 00,
  254. 16, 16, 00, 00,
  255. 00, 00, 16, 00,
  256. 16, 00, 16, 00,
  257. 00, 16, 16, 00,
  258. 24, 24, 24, 00,
  259. 16, 16, 16, 00,
  260. 31, 00, 00, 00,
  261. 00, 31, 00, 00,
  262. 31, 31, 00, 00,
  263. 00, 00, 31, 00,
  264. 31, 00, 31, 00,
  265. 00, 31, 31, 00,
  266. 31, 31, 31, 00
  267. };
  268. /*****************************************************************************
  269. *
  270. * MapVGA
  271. *
  272. *****************************************************************************/
  273. __inline BYTE MapVGA(BYTE r, BYTE g, BYTE b)
  274. {
  275. int i;
  276. //
  277. // build index into vga_map (r,g,b in range of 0-31)
  278. //
  279. i = ((b & 0x18) >> 3) | ((g & 0x18) >> 1) | ((r & 0x18) << 1);
  280. //
  281. // lookup in our "quick map" table
  282. //
  283. i = (int)vga_map[i];
  284. if (i & 0xFFF0)
  285. {
  286. //
  287. // more than one color is close, do a eclidian search of
  288. // at most three colors.
  289. //
  290. int e1,e,n,n1;
  291. e1 = 0x7fffffff;
  292. while (i)
  293. {
  294. n = i & 0x000F;
  295. e = ((int)VGAColors[n].r - r) * ((int)VGAColors[n].r - r) +
  296. ((int)VGAColors[n].g - g) * ((int)VGAColors[n].g - g) +
  297. ((int)VGAColors[n].b - b) * ((int)VGAColors[n].b - b) ;
  298. if (e < e1)
  299. {
  300. n1 = n;
  301. e1 = e;
  302. }
  303. i = i >> 4;
  304. }
  305. return (BYTE)n1;
  306. }
  307. else
  308. {
  309. //
  310. // one one color matchs, we are done
  311. //
  312. return (BYTE)(i & 0x000F);
  313. }
  314. }
  315. /*****************************************************************************
  316. *
  317. * MakeITableVGA
  318. *
  319. * build a 32k color inverse table to the VGA colors
  320. *
  321. *****************************************************************************/
  322. BOOL MakeITableVGA(PIMAP lpITable)
  323. {
  324. PIMAP pb;
  325. BYTE r,g,b;
  326. pb = lpITable;
  327. for (r=0;r<32;r++)
  328. for (g=0;g<32;g++)
  329. for (b=0;b<32;b++)
  330. *pb++ = (BYTE)MapVGA(r,g,b);
  331. return TRUE;
  332. }
  333. /*****************************************************************************
  334. *
  335. * MakeITableDEF
  336. *
  337. * build a 32k color inverse table to the DEFAULT_PALETTE
  338. * just builds a VGA ITable then bumps up values above 7
  339. *
  340. *****************************************************************************/
  341. BOOL MakeITableDEF(PIMAP pb)
  342. {
  343. int i;
  344. MakeITableVGA(pb);
  345. for (i=0;i<0x8000;i++)
  346. if (pb[i] >= 8)
  347. pb[i] += 240;
  348. return TRUE;
  349. }
  350. /*****************************************************************************
  351. *
  352. * MakeITableMono
  353. *
  354. * build a 32k color inverse table to black/white
  355. *
  356. *****************************************************************************/
  357. BOOL MakeITableMono(PIMAP lpITable)
  358. {
  359. PIMAP pb;
  360. BYTE r,g,b;
  361. pb = lpITable;
  362. for (r=0;r<32;r++)
  363. for (g=0;g<32;g++)
  364. for (b=0;b<32;b++)
  365. *pb++ = (g/2 + (r+b)/4) > 15;
  366. return TRUE;
  367. }
  368. /*****************************************************************
  369. * TAG( inv_cmap )
  370. *
  371. * Compute an inverse colormap efficiently.
  372. * Inputs:
  373. * colors: Number of colors in the forward colormap.
  374. * colormap: The forward colormap.
  375. * bits: Number of quantization bits. The inverse
  376. * colormap will have (2^bits)^3 entries.
  377. * dist_buf: An array of (2^bits)^3 long integers to be
  378. * used as scratch space.
  379. * Outputs:
  380. * rgbmap: The output inverse colormap. The entry
  381. * rgbmap[(r<<(2*bits)) + (g<<bits) + b]
  382. * is the colormap entry that is closest to the
  383. * (quantized) color (r,g,b).
  384. * Assumptions:
  385. * Quantization is performed by right shift (low order bits are
  386. * truncated). Thus, the distance to a quantized color is
  387. * actually measured to the color at the center of the cell
  388. * (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
  389. * Algorithm:
  390. * Uses a "distance buffer" algorithm:
  391. * The distance from each representative in the forward color map
  392. * to each point in the rgb space is computed. If it is less
  393. * than the distance currently stored in dist_buf, then the
  394. * corresponding entry in rgbmap is replaced with the current
  395. * representative (and the dist_buf entry is replaced with the
  396. * new distance).
  397. *
  398. * The distance computation uses an efficient incremental formulation.
  399. *
  400. * Distances are computed "outward" from each color. If the
  401. * colors are evenly distributed in color space, the expected
  402. * number of cells visited for color I is N^3/I.
  403. * Thus, the complexity of the algorithm is O(log(K) N^3),
  404. * where K = colors, and N = 2^bits.
  405. */
  406. /*
  407. * Here's the idea: scan from the "center" of each cell "out"
  408. * until we hit the "edge" of the cell -- that is, the point
  409. * at which some other color is closer -- and stop. In 1-D,
  410. * this is simple:
  411. * for i := here to max do
  412. * if closer then buffer[i] = this color
  413. * else break
  414. * repeat above loop with i := here-1 to min by -1
  415. *
  416. * In 2-D, it's trickier, because along a "scan-line", the
  417. * region might start "after" the "center" point. A picture
  418. * might clarify:
  419. * | ...
  420. * | ... .
  421. * ... .
  422. * ... | .
  423. * . + .
  424. * . .
  425. * . .
  426. * .........
  427. *
  428. * The + marks the "center" of the above region. On the top 2
  429. * lines, the region "begins" to the right of the "center".
  430. *
  431. * Thus, we need a loop like this:
  432. * detect := false
  433. * for i := here to max do
  434. * if closer then
  435. * buffer[..., i] := this color
  436. * if !detect then
  437. * here = i
  438. * detect = true
  439. * else
  440. * if detect then
  441. * break
  442. *
  443. * Repeat the above loop with i := here-1 to min by -1. Note that
  444. * the "detect" value should not be reinitialized. If it was
  445. * "true", and center is not inside the cell, then none of the
  446. * cell lies to the left and this loop should exit
  447. * immediately.
  448. *
  449. * The outer loops are similar, except that the "closer" test
  450. * is replaced by a call to the "next in" loop; its "detect"
  451. * value serves as the test. (No assignment to the buffer is
  452. * done, either.)
  453. *
  454. * Each time an outer loop starts, the "here", "min", and
  455. * "max" values of the next inner loop should be
  456. * re-initialized to the center of the cell, 0, and cube size,
  457. * respectively. Otherwise, these values will carry over from
  458. * one "call" to the inner loop to the next. This tracks the
  459. * edges of the cell and minimizes the number of
  460. * "unproductive" comparisons that must be made.
  461. *
  462. * Finally, the inner-most loop can have the "if !detect"
  463. * optimized out of it by splitting it into two loops: one
  464. * that finds the first color value on the scan line that is
  465. * in this cell, and a second that fills the cell until
  466. * another one is closer:
  467. * if !detect then {needed for "down" loop}
  468. * for i := here to max do
  469. * if closer then
  470. * buffer[..., i] := this color
  471. * detect := true
  472. * break
  473. * for i := i+1 to max do
  474. * if closer then
  475. * buffer[..., i] := this color
  476. * else
  477. * break
  478. *
  479. * In this implementation, each level will require the
  480. * following variables. Variables labelled (l) are local to each
  481. * procedure. The ? should be replaced with r, g, or b:
  482. * cdist: The distance at the starting point.
  483. * ?center: The value of this component of the color
  484. * c?inc: The initial increment at the ?center position.
  485. * ?stride: The amount to add to the buffer
  486. * pointers (dp and rgbp) to get to the
  487. * "next row".
  488. * min(l): The "low edge" of the cell, init to 0
  489. * max(l): The "high edge" of the cell, init to
  490. * colormax-1
  491. * detect(l): True if this row has changed some
  492. * buffer entries.
  493. * i(l): The index for this row.
  494. * ?xx: The accumulated increment value.
  495. *
  496. * here(l): The starting index for this color. The
  497. * following variables are associated with here,
  498. * in the sense that they must be updated if here
  499. * is changed.
  500. * ?dist: The current distance for this level. The
  501. * value of dist from the previous level (g or r,
  502. * for level b or g) initializes dist on this
  503. * level. Thus gdist is associated with here(b)).
  504. * ?inc: The initial increment for the row.
  505. *
  506. * ?dp: Pointer into the distance buffer. The value
  507. * from the previous level initializes this level.
  508. * ?rgbp: Pointer into the rgb buffer. The value
  509. * from the previous level initializes this level.
  510. *
  511. * The blue and green levels modify 'here-associated' variables (dp,
  512. * rgbp, dist) on the green and red levels, respectively, when here is
  513. * changed.
  514. */
  515. static int bcenter, gcenter, rcenter;
  516. static long gdist, rdist, cdist;
  517. static long cbinc, cginc, crinc;
  518. static PDIST gdp;
  519. static PDIST rdp;
  520. static PDIST cdp;
  521. static PIMAP grgbp;
  522. static PIMAP rrgbp;
  523. static PIMAP crgbp;
  524. static int gstride, rstride;
  525. static long x, xsqr, colormax;
  526. static int cindex;
  527. int redloop(void);
  528. int greenloop( int restart );
  529. int blueloop( int restart );
  530. void maxfill( PDIST buffer, long side);
  531. /* Track minimum and maximum. */
  532. #define MINMAX_TRACK
  533. void
  534. inv_cmap(int colors, RGBX FAR *colormap, int bits,
  535. PDIST dist_buf, PIMAP rgbmap )
  536. {
  537. int nbits = 8 - bits;
  538. colormax = 1 << bits;
  539. x = 1 << nbits;
  540. xsqr = 1 << (2 * nbits);
  541. /* Compute "strides" for accessing the arrays. */
  542. gstride = (int) colormax;
  543. rstride = (int) (colormax * colormax);
  544. maxfill( dist_buf, colormax );
  545. for ( cindex = 0; cindex < colors; cindex++ )
  546. {
  547. /*
  548. * Distance formula is
  549. * (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
  550. *
  551. * Because of quantization, we will measure from the center of
  552. * each quantized "cube", so blue distance is
  553. * (blue + x/2 - map[2])^2,
  554. * where x = 2^(8 - bits).
  555. * The step size is x, so the blue increment is
  556. * 2*x*blue - 2*x*map[2] + 2*x^2
  557. *
  558. * Now, b in the code below is actually blue/x, so our
  559. * increment will be 2*(b*x^2 + x^2 - x*map[2]). For
  560. * efficiency, we will maintain this quantity in a separate variable
  561. * that will be updated incrementally by adding 2*x^2 each time.
  562. */
  563. /* The initial position is the cell containing the colormap
  564. * entry. We get this by quantizing the colormap values.
  565. */
  566. rcenter = colormap[cindex].r >> nbits;
  567. gcenter = colormap[cindex].g >> nbits;
  568. bcenter = colormap[cindex].b >> nbits;
  569. rdist = colormap[cindex].r - (rcenter * x + x/2);
  570. gdist = colormap[cindex].g - (gcenter * x + x/2);
  571. cdist = colormap[cindex].b - (bcenter * x + x/2);
  572. cdist = rdist*rdist + gdist*gdist + cdist*cdist;
  573. crinc = 2 * ((rcenter + 1) * xsqr - (colormap[cindex].r * x));
  574. cginc = 2 * ((gcenter + 1) * xsqr - (colormap[cindex].g * x));
  575. cbinc = 2 * ((bcenter + 1) * xsqr - (colormap[cindex].b * x));
  576. /* Array starting points. */
  577. cdp = dist_buf + rcenter * rstride + gcenter * gstride + bcenter;
  578. crgbp = rgbmap + rcenter * rstride + gcenter * gstride + bcenter;
  579. (void)redloop();
  580. }
  581. }
  582. /* redloop -- loop up and down from red center. */
  583. int
  584. redloop()
  585. {
  586. int detect;
  587. int r, i = cindex;
  588. int first;
  589. long txsqr = xsqr + xsqr;
  590. static long rxx;
  591. detect = 0;
  592. /* Basic loop up. */
  593. for ( r = rcenter, rdist = cdist, rxx = crinc,
  594. rdp = cdp, rrgbp = crgbp, first = 1;
  595. r < (int) colormax;
  596. r++, rdp += rstride, rrgbp += rstride,
  597. rdist += rxx, rxx += txsqr, first = 0 )
  598. {
  599. if ( greenloop( first ) )
  600. detect = 1;
  601. else if ( detect )
  602. break;
  603. }
  604. /* Basic loop down. */
  605. for ( r = rcenter - 1, rxx = crinc - txsqr, rdist = cdist - rxx,
  606. rdp = cdp - rstride, rrgbp = crgbp - rstride, first = 1;
  607. r >= 0;
  608. r--, rdp -= rstride, rrgbp -= rstride,
  609. rxx -= txsqr, rdist -= rxx, first = 0 )
  610. {
  611. if ( greenloop( first ) )
  612. detect = 1;
  613. else if ( detect )
  614. break;
  615. }
  616. return detect;
  617. }
  618. /* greenloop -- loop up and down from green center. */
  619. int
  620. greenloop( int restart )
  621. {
  622. int detect;
  623. int g, i = cindex;
  624. int first;
  625. long txsqr = xsqr + xsqr;
  626. static int here, min, max;
  627. #ifdef MINMAX_TRACK
  628. static int prevmax, prevmin;
  629. int thismax, thismin;
  630. #endif
  631. static long ginc, gxx, gcdist; /* "gc" variables maintain correct */
  632. static PDIST gcdp; /* values for bcenter position, */
  633. static PIMAP gcrgbp; /* despite modifications by blueloop */
  634. /* to gdist, gdp, grgbp. */
  635. if ( restart )
  636. {
  637. here = gcenter;
  638. min = 0;
  639. max = (int) colormax - 1;
  640. ginc = cginc;
  641. #ifdef MINMAX_TRACK
  642. prevmax = 0;
  643. prevmin = (int) colormax;
  644. #endif
  645. }
  646. #ifdef MINMAX_TRACK
  647. thismin = min;
  648. thismax = max;
  649. #endif
  650. detect = 0;
  651. /* Basic loop up. */
  652. for ( g = here, gcdist = gdist = rdist, gxx = ginc,
  653. gcdp = gdp = rdp, gcrgbp = grgbp = rrgbp, first = 1;
  654. g <= max;
  655. g++, gdp += gstride, gcdp += gstride, grgbp += gstride, gcrgbp += gstride,
  656. gdist += gxx, gcdist += gxx, gxx += txsqr, first = 0 )
  657. {
  658. if ( blueloop( first ) )
  659. {
  660. if ( !detect )
  661. {
  662. /* Remember here and associated data! */
  663. if ( g > here )
  664. {
  665. here = g;
  666. rdp = gcdp;
  667. rrgbp = gcrgbp;
  668. rdist = gcdist;
  669. ginc = gxx;
  670. #ifdef MINMAX_TRACK
  671. thismin = here;
  672. #endif
  673. }
  674. detect = 1;
  675. }
  676. }
  677. else if ( detect )
  678. {
  679. #ifdef MINMAX_TRACK
  680. thismax = g - 1;
  681. #endif
  682. break;
  683. }
  684. }
  685. /* Basic loop down. */
  686. for ( g = here - 1, gxx = ginc - txsqr, gcdist = gdist = rdist - gxx,
  687. gcdp = gdp = rdp - gstride, gcrgbp = grgbp = rrgbp - gstride,
  688. first = 1;
  689. g >= min;
  690. g--, gdp -= gstride, gcdp -= gstride, grgbp -= gstride, gcrgbp -= gstride,
  691. gxx -= txsqr, gdist -= gxx, gcdist -= gxx, first = 0 )
  692. {
  693. if ( blueloop( first ) )
  694. {
  695. if ( !detect )
  696. {
  697. /* Remember here! */
  698. here = g;
  699. rdp = gcdp;
  700. rrgbp = gcrgbp;
  701. rdist = gcdist;
  702. ginc = gxx;
  703. #ifdef MINMAX_TRACK
  704. thismax = here;
  705. #endif
  706. detect = 1;
  707. }
  708. }
  709. else if ( detect )
  710. {
  711. #ifdef MINMAX_TRACK
  712. thismin = g + 1;
  713. #endif
  714. break;
  715. }
  716. }
  717. #ifdef MINMAX_TRACK
  718. /* If we saw something, update the edge trackers. For now, only
  719. * tracks edges that are "shrinking" (min increasing, max
  720. * decreasing.
  721. */
  722. if ( detect )
  723. {
  724. if ( thismax < prevmax )
  725. max = thismax;
  726. prevmax = thismax;
  727. if ( thismin > prevmin )
  728. min = thismin;
  729. prevmin = thismin;
  730. }
  731. #endif
  732. return detect;
  733. }
  734. /* blueloop -- loop up and down from blue center. */
  735. int
  736. blueloop( int restart )
  737. {
  738. int detect;
  739. register PDIST dp;
  740. register PIMAP rgbp;
  741. register long bdist, bxx;
  742. register int b, i = cindex;
  743. register long txsqr = xsqr + xsqr;
  744. register int lim;
  745. static int here, min, max;
  746. #ifdef MINMAX_TRACK
  747. static int prevmin, prevmax;
  748. int thismin, thismax;
  749. #endif /* MINMAX_TRACK */
  750. static long binc;
  751. if ( restart )
  752. {
  753. here = bcenter;
  754. min = 0;
  755. max = (int) colormax - 1;
  756. binc = cbinc;
  757. #ifdef MINMAX_TRACK
  758. prevmin = (int) colormax;
  759. prevmax = 0;
  760. #endif /* MINMAX_TRACK */
  761. }
  762. detect = 0;
  763. #ifdef MINMAX_TRACK
  764. thismin = min;
  765. thismax = max;
  766. #endif
  767. /* Basic loop up. */
  768. /* First loop just finds first applicable cell. */
  769. for ( b = here, bdist = gdist, bxx = binc, dp = gdp, rgbp = grgbp, lim = max;
  770. b <= lim;
  771. b++, dp++, rgbp++,
  772. bdist += bxx, bxx += txsqr )
  773. {
  774. if ( *dp > (DWORD)bdist )
  775. {
  776. /* Remember new 'here' and associated data! */
  777. if ( b > here )
  778. {
  779. here = b;
  780. gdp = dp;
  781. grgbp = rgbp;
  782. gdist = bdist;
  783. binc = bxx;
  784. #ifdef MINMAX_TRACK
  785. thismin = here;
  786. #endif
  787. }
  788. detect = 1;
  789. break;
  790. }
  791. }
  792. /* Second loop fills in a run of closer cells. */
  793. for ( ;
  794. b <= lim;
  795. b++, dp++, rgbp++,
  796. bdist += bxx, bxx += txsqr )
  797. {
  798. if ( *dp > (DWORD)bdist )
  799. {
  800. *dp = bdist;
  801. *rgbp = (BYTE) i;
  802. }
  803. else
  804. {
  805. #ifdef MINMAX_TRACK
  806. thismax = b - 1;
  807. #endif
  808. break;
  809. }
  810. }
  811. /* Basic loop down. */
  812. /* Do initializations here, since the 'find' loop might not get
  813. * executed.
  814. */
  815. lim = min;
  816. b = here - 1;
  817. bxx = binc - txsqr;
  818. bdist = gdist - bxx;
  819. dp = gdp - 1;
  820. rgbp = grgbp - 1;
  821. /* The 'find' loop is executed only if we didn't already find
  822. * something.
  823. */
  824. if ( !detect )
  825. for ( ;
  826. b >= lim;
  827. b--, dp--, rgbp--,
  828. bxx -= txsqr, bdist -= bxx )
  829. {
  830. if ( *dp > (DWORD)bdist )
  831. {
  832. /* Remember here! */
  833. /* No test for b against here necessary because b <
  834. * here by definition.
  835. */
  836. here = b;
  837. gdp = dp;
  838. grgbp = rgbp;
  839. gdist = bdist;
  840. binc = bxx;
  841. #ifdef MINMAX_TRACK
  842. thismax = here;
  843. #endif
  844. detect = 1;
  845. break;
  846. }
  847. }
  848. /* The 'update' loop. */
  849. for ( ;
  850. b >= lim;
  851. b--, dp--, rgbp--,
  852. bxx -= txsqr, bdist -= bxx )
  853. {
  854. if ( *dp > (DWORD)bdist )
  855. {
  856. *dp = bdist;
  857. *rgbp = (BYTE) i;
  858. }
  859. else
  860. {
  861. #ifdef MINMAX_TRACK
  862. thismin = b + 1;
  863. #endif
  864. break;
  865. }
  866. }
  867. /* If we saw something, update the edge trackers. */
  868. #ifdef MINMAX_TRACK
  869. if ( detect )
  870. {
  871. /* Only tracks edges that are "shrinking" (min increasing, max
  872. * decreasing.
  873. */
  874. if ( thismax < prevmax )
  875. max = thismax;
  876. if ( thismin > prevmin )
  877. min = thismin;
  878. /* Remember the min and max values. */
  879. prevmax = thismax;
  880. prevmin = thismin;
  881. }
  882. #endif /* MINMAX_TRACK */
  883. return detect;
  884. }
  885. void maxfill(PDIST buffer, long side)
  886. {
  887. register unsigned long maxv = (unsigned long)~0L;
  888. register long i;
  889. register PDIST bp;
  890. for ( i = colormax * colormax * colormax, bp = buffer;
  891. i > 0;
  892. i--, bp++ )
  893. *bp = maxv;
  894. }