Lunatic: add a 'lastokcol' argument to engine.nearcolor() and document it.

On the C side, slightly rewrite (now) getclosestcol_lim() for clarity.

git-svn-id: https://svn.eduke32.com/eduke32@4308 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2014-02-08 14:37:58 +00:00
parent 5726a15bb3
commit a9fb9e6356
5 changed files with 61 additions and 24 deletions

View file

@ -1244,7 +1244,12 @@ static inline int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsoti
int32_t screencapture(const char *filename, char inverseit, const char *versionstr) ATTRIBUTE((nonnull(1))); int32_t screencapture(const char *filename, char inverseit, const char *versionstr) ATTRIBUTE((nonnull(1)));
int32_t getclosestcol(int32_t r, int32_t g, int32_t b); static inline int32_t getclosestcol(int32_t r, int32_t g, int32_t b)
{
extern int32_t getclosestcol_lim(int32_t r, int32_t g, int32_t b, int32_t lastokcol);
return getclosestcol_lim(r, g, b, 255);
}
// PLAG: line utility functions // PLAG: line utility functions
typedef struct s_equation { typedef struct s_equation {

View file

@ -8104,34 +8104,39 @@ static int32_t loadpalette(void)
} }
// // Finds a color index in [0 .. lastokcol] closest to (r, g, b).
// getclosestcol // <lastokcol> must be in [0 .. 255].
// int32_t getclosestcol_lim(int32_t r, int32_t g, int32_t b, int32_t lastokcol)
int32_t getclosestcol(int32_t r, int32_t g, int32_t b)
{ {
int32_t i, j, k, dist, mindist, retcol; int32_t i, k, retcol = -1;
const char *pal1;
j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ const int32_t j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ
+ (g>>3)*FASTPALGRIDSIZ + (b>>3) + (g>>3)*FASTPALGRIDSIZ + (b>>3)
+ FASTPALGRIDSIZ*FASTPALGRIDSIZ + FASTPALGRIDSIZ*FASTPALGRIDSIZ
+ FASTPALGRIDSIZ+1; + FASTPALGRIDSIZ+1;
mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
int32_t mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
mindist = min(mindist,bdist[coldist[b&7]+64+8]); mindist = min(mindist,bdist[coldist[b&7]+64+8]);
mindist++; mindist++;
Bassert(lastokcol >= 0 && lastokcol <= 255);
r = 64-r; g = 64-g; b = 64-b; r = 64-r; g = 64-g; b = 64-b;
retcol = -1;
for (k=26; k>=0; k--) for (k=26; k>=0; k--)
{ {
i = colscan[k]+j; if ((colhere[i>>3]&pow2char[i&7]) == 0) continue; i = colscan[k]+j;
if ((colhere[i>>3]&pow2char[i&7]) == 0)
continue;
i = colhead[i]; i = colhead[i];
do do
{ {
pal1 = (char *)&palette[i*3]; const char *pal1 = (char *)&palette[i*3];
dist = gdist[pal1[1]+g]; int32_t dist = gdist[pal1[1]+g];
if (dist < mindist)
if (dist < mindist && i <= lastokcol)
{ {
dist += rdist[pal1[0]+r]; dist += rdist[pal1[0]+r];
if (dist < mindist) if (dist < mindist)
@ -8140,22 +8145,29 @@ int32_t getclosestcol(int32_t r, int32_t g, int32_t b)
if (dist < mindist) { mindist = dist; retcol = i; } if (dist < mindist) { mindist = dist; retcol = i; }
} }
} }
i = colnext[i]; i = colnext[i];
} }
while (i >= 0); while (i >= 0);
} }
if (retcol >= 0) return(retcol);
if (retcol >= 0)
return retcol;
mindist = INT32_MAX; mindist = INT32_MAX;
pal1 = (char *)&palette[768-3];
for (i=255; i>=0; i--,pal1-=3) for (i=lastokcol; i>=0; i--)
{ {
dist = gdist[pal1[1]+g]; if (dist >= mindist) continue; const char *pal1 = (char *)&palette[i*3];
int32_t dist = gdist[pal1[1]+g]; if (dist >= mindist) continue;
dist += rdist[pal1[0]+r]; if (dist >= mindist) continue; dist += rdist[pal1[0]+r]; if (dist >= mindist) continue;
dist += bdist[pal1[2]+b]; if (dist >= mindist) continue; dist += bdist[pal1[2]+b]; if (dist >= mindist) continue;
mindist = dist; retcol = i; mindist = dist; retcol = i;
} }
return(retcol);
return retcol;
} }

View file

@ -2065,6 +2065,20 @@ for color index `i`. The color components are in the range [0 .. 63].
If `i` is 255, `r`, `g` and `b` are all returned as 0, even if the actual base If `i` is 255, `r`, `g` and `b` are all returned as 0, even if the actual base
palette may contain different values for that index. palette may contain different values for that index.
`i = engine.nearcolor(r, g, b [, lastokcol])`::
Given the red, green and blue components `r`, `g` and `b` of a query color,
returns the color index `i` whose color in the default base palette is closest
to the query color. ``Closeness'' is established using an Euclidean distance
with a weighting on the color components.
+
The optional argument `lastokcol` can be used to restrict the range of color
indices to search: the returned color index is guaranteed to be in the range
[0{nbsp}..{nbsp}`lastokcol`]. It defaults 255, so that all colors are
searched.footnote:[For example, it may be desirable to omit ``fullbright''
colors from being returned. The shade table loaded from Duke3D's PALETTE.DAT
makes color indices 240--254 fullbright, so passing 239 to `lastokcol` achieves
the mentioned filtering.]
Shade table interfaces Shade table interfaces
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -14,7 +14,7 @@ local ismapster32 = (C.LUNATIC_CLIENT == C.LUNATIC_CLIENT_MAPSTER32)
---------- ----------
decl[[ decl[[
int32_t getclosestcol(int32_t r, int32_t g, int32_t b); int32_t getclosestcol_lim(int32_t r, int32_t g, int32_t b, int32_t lastokcol);
char *palookup[256]; // MAXPALOOKUPS char *palookup[256]; // MAXPALOOKUPS
uint8_t palette[768]; uint8_t palette[768];
@ -211,12 +211,18 @@ function engine.getrgb(colidx)
return rgbptr[0], rgbptr[1], rgbptr[2] return rgbptr[0], rgbptr[1], rgbptr[2]
end end
-- TODO: flag whether fullbrights are OK function engine.nearcolor(r, g, b, lastokcol)
function engine.nearcolor(r, g, b)
check_colcomp(r) check_colcomp(r)
check_colcomp(g) check_colcomp(g)
check_colcomp(b) check_colcomp(b)
return C.getclosestcol(r, g, b)
if (lastokcol == nil) then
lastokcol = 255
elseif (type(lastokcol)~="number" or not (lastokcol >= 0 and lastokcol <= 255)) then
error("invalid argument #4 <lastokcol>: must be in the range [0 .. 255]", 2)
end
return C.getclosestcol_lim(r, g, b, lastokcol)
end end

View file

@ -303,7 +303,7 @@ function shadexfog.create_additive_trans(blendidx)
local r,g,b = engine.getrgb(i) local r,g,b = engine.getrgb(i)
local R,G,B = engine.getrgb(j) local R,G,B = engine.getrgb(j)
tab[i][j] = engine.nearcolor(min(r+R, 63), min(g+G, 63), min(b+B, 63)) tab[i][j] = engine.nearcolor(min(r+R, 63), min(g+G, 63), min(b+B, 63), 255-16)
end end
end end