|  | #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; | 
|  | } |