void ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) { int i, j; unsigned int dmin[256], dmax; int r0, g0, b0; int r1, g1, b1; int rc, gc, bc; unsigned int d[BOXVOLUME]; UINT8 c[BOXVOLUME]; /* Get box boundaries for the given (r,g,b)-triplet. Each box covers eight cache slots (32 colour values, that is). */ r0 = r & 0xe0; r1 = r0 + 0x1f; rc = (r0 + r1) / 2; g0 = g & 0xe0; g1 = g0 + 0x1f; gc = (g0 + g1) / 2; b0 = b & 0xe0; b1 = b0 + 0x1f; bc = (b0 + b1) / 2; /* Step 1 -- Select relevant palette entries (after Heckbert) */ /* For each palette entry, calculate the min and max distances to * any position in the box given by the colour we're looking for. */ dmax = (unsigned int) ~0; for (i = 0; i < 256; i++) { int r, g, b; unsigned int tmin, tmax; /* Find min and max distances to any point in the box */ r = palette->palette[i*4+0]; tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0; tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0); g = palette->palette[i*4+1]; tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0; tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0); b = palette->palette[i*4+2]; tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0; tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); dmin[i] = tmin; if (tmax < dmax) dmax = tmax; /* keep the smallest max distance only */ } /* Step 2 -- Incrementally update cache slot (after Thomas) */ /* Find the box containing the nearest palette entry, and update * all slots in that box. We only check boxes for which the min * distance is less than or equal the smallest max distance */ for (i = 0; i < BOXVOLUME; i++) d[i] = (unsigned int) ~0; for (i = 0; i < 256; i++) if (dmin[i] <= dmax) { int rd, gd, bd; int ri, gi, bi; int rx, gx, bx; ri = (r0 - palette->palette[i*4+0]) * RSCALE; gi = (g0 - palette->palette[i*4+1]) * GSCALE; bi = (b0 - palette->palette[i*4+2]) * BSCALE; rd = ri*ri + gi*gi + bi*bi; ri = ri * (2 * RSTEP) + RSTEP * RSTEP; gi = gi * (2 * GSTEP) + GSTEP * GSTEP; bi = bi * (2 * BSTEP) + BSTEP * BSTEP; rx = ri; for (r = j = 0; r < BOX; r++) { gd = rd; gx = gi; for (g = 0; g < BOX; g++) { bd = gd; bx = bi; for (b = 0; b < BOX; b++) { if ((unsigned int) bd < d[j]) { d[j] = bd; c[j] = (UINT8) i; } bd += bx; bx += 2 * BSTEP * BSTEP; j++; } gd += gx; gx += 2 * GSTEP * GSTEP; } rd += rx; rx += 2 * RSTEP * RSTEP; } } /* Step 3 -- Update cache */ /* The c array now contains the closest match for each * cache slot in the box. Update the cache. */ j = 0; for (r = r0; r < r1; r+=4) for (g = g0; g < g1; g+=4) for (b = b0; b < b1; b+=4) ImagingPaletteCache(palette, r, g, b) = c[j++]; }
static void compute_edge_graph ( bitmap_t * tmap, /* IN - valid set of terminals */ bitmap_t * fset_mask, /* IN - valid FSTs */ struct cinfo * cip /* IN - compatibility info */ ) { int i, j, i1, i2; int sp_index; int sp_total; int n2edges; int nedges; struct full_set * fsp; struct pset * terms; struct point * p1; struct point * p2; dist_t d = 0.0; char buf1 [128]; char buf2 [128]; /* Total number of Steiner points and ordinary edges */ nedges = cip -> num_edges; sp_total = 0; n2edges = 0; for (i = 0; i < nedges; i++) { if (NOT BITON (fset_mask, i)) continue; sp_total += cip -> full_trees [i] -> steiners -> n; n2edges += cip -> full_trees [i] -> nedges; } /* Write header */ if (Print_ORLibrary_Format) { printf ("%d %d\n", cip -> num_verts + sp_total, n2edges); } if (Print_SteinLib_Format) { printf ("33d32945 STP File, STP Format Version 1.00\n" "Section Comment\n" "Name \"%s\"\n" "Creator \"GeoSteiner\"\n" "Remark \"Reduced graph from FST generator\"\n" "End\n\n" "Section Graph\n" "Nodes %d\n" "Edges %d\n", cip -> description, cip -> num_verts + sp_total, n2edges); } /* Write (ordinary) graph edges */ sp_index = cip -> num_verts; for (i = 0; i < nedges; i++) { if (NOT BITON (fset_mask, i)) continue; fsp = cip -> full_trees [i]; terms = fsp -> terminals; for (j = 0; j < fsp -> nedges; j++) { /* Compute length of this edge */ p1 = (fsp -> edges[j].p1 < terms -> n) ? &(terms -> a[ fsp -> edges[j].p1 ]) : &(fsp -> steiners -> a [fsp -> edges[j].p1 - terms -> n]); p2 = (fsp -> edges[j].p2 < terms -> n) ? &(terms -> a[ fsp -> edges[j].p2 ]) : &(fsp -> steiners -> a [fsp -> edges[j].p2 - terms -> n]); i1 = (fsp -> edges[j].p1 < terms -> n) ? terms -> a[ fsp -> edges[j].p1 ].pnum + 1 : fsp -> edges[j].p1 - terms -> n + sp_index + 1; i2 = (fsp -> edges[j].p2 < terms -> n) ? terms -> a[ fsp -> edges[j].p2 ].pnum + 1 : fsp -> edges[j].p2 - terms -> n + sp_index + 1; if (Print_SteinLib_Format) { printf ("E "); } if (cip -> metric EQ EUCLIDEAN) { d = EDIST(p1, p2); } else { d = RDIST(p1, p2); } dist_to_string (buf1, d, &(cip -> scale)); printf ("%d %d %s\n", i1, i2, buf1); } if (fsp -> steiners NE NULL) { sp_index += fsp -> steiners -> n; } } /* Write terminals (and coordinates in STP-format) */ if (Print_ORLibrary_Format) { printf ("%d\n", cip -> num_verts); for (i = 0; i < cip -> num_verts; i++) { printf ("%d\n", i+1); } } if (Print_SteinLib_Format) { printf ("End\n\n" "Section Terminals\n" "Terminals %d\n", cip -> num_verts); for (i = 0; i < cip -> num_verts; i++) { printf ("T %d\n", i+1); } printf ("End\n\n" "Section Coordinates\n"); for (i = 0; i < cip -> num_verts; i++) { /* terminals */ dist_to_string (buf1, cip -> pts -> a[i].x, &(cip -> scale)); dist_to_string (buf2, cip -> pts -> a[i].y, &(cip -> scale)); printf ("DD %d %s %s\n", i+1, buf1, buf2); } sp_index = cip -> num_verts + 1; for (i = 0; i < nedges; i++) { /* Steiner points */ fsp = cip -> full_trees [i]; for (j = 0; j < fsp -> steiners -> n; j++) { dist_to_string (buf1, fsp -> steiners -> a[j].x, &(cip -> scale)); dist_to_string (buf2, fsp -> steiners -> a[j].y, &(cip -> scale)); printf ("DD %d %s %s\n", sp_index++, buf1, buf2); } } printf ("End\n\n" "EOF\n"); } }