#include <u.h> | |
#include <libc.h> | |
#include <draw.h> | |
/* | |
* This original version, although fast and a true inverse of | |
* cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c)) | |
* returned the original color, does a terrible job for RGB | |
* triples that do not appear in the color map, so it has been | |
* replaced by the much slower version below, that loops | |
* over the color map looking for the nearest point in RGB | |
* space. There is no visual psychology reason for that | |
* criterion, but it's easy to implement and the results are | |
* far more pleasing. | |
* | |
int | |
rgb2cmap(int cr, int cg, int cb) | |
{ | |
int r, g, b, v, cv; | |
if(cr < 0) | |
cr = 0; | |
else if(cr > 255) | |
cr = 255; | |
if(cg < 0) | |
cg = 0; | |
else if(cg > 255) | |
cg = 255; | |
if(cb < 0) | |
cb = 0; | |
else if(cb > 255) | |
cb = 255; | |
r = cr>>6; | |
g = cg>>6; | |
b = cb>>6; | |
cv = cr; | |
if(cg > cv) | |
cv = cg; | |
if(cb > cv) | |
cv = cb; | |
v = (cv>>4)&3; | |
return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15)); | |
} | |
*/ | |
int | |
rgb2cmap(int cr, int cg, int cb) | |
{ | |
int i, r, g, b, sq; | |
u32int rgb; | |
int best, bestsq; | |
best = 0; | |
bestsq = 0x7FFFFFFF; | |
for(i=0; i<256; i++){ | |
rgb = cmap2rgb(i); | |
r = (rgb>>16) & 0xFF; | |
g = (rgb>>8) & 0xFF; | |
b = (rgb>>0) & 0xFF; | |
sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb); | |
if(sq < bestsq){ | |
bestsq = sq; | |
best = i; | |
} | |
} | |
return best; | |
} | |
int | |
cmap2rgb(int c) | |
{ | |
int j, num, den, r, g, b, v, rgb; | |
r = c>>6; | |
v = (c>>4)&3; | |
j = (c-v+r)&15; | |
g = j>>2; | |
b = j&3; | |
den=r; | |
if(g>den) | |
den=g; | |
if(b>den) | |
den=b; | |
if(den==0) { | |
v *= 17; | |
rgb = (v<<16)|(v<<8)|v; | |
} | |
else{ | |
num=17*(4*den+v); | |
rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den); | |
} | |
return rgb; | |
} | |
int | |
cmap2rgba(int c) | |
{ | |
return (cmap2rgb(c)<<8)|0xFF; | |
} |