diff options
Diffstat (limited to 'src/libdraw/rgb.c')
-rw-r--r-- | src/libdraw/rgb.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/libdraw/rgb.c b/src/libdraw/rgb.c new file mode 100644 index 00000000..e8f7f51b --- /dev/null +++ b/src/libdraw/rgb.c @@ -0,0 +1,99 @@ +#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; +} |