rgb.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. /*
  5. * This original version, although fast and a true inverse of
  6. * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c))
  7. * returned the original color, does a terrible job for RGB
  8. * triples that do not appear in the color map, so it has been
  9. * replaced by the much slower version below, that loops
  10. * over the color map looking for the nearest point in RGB
  11. * space. There is no visual psychology reason for that
  12. * criterion, but it's easy to implement and the results are
  13. * far more pleasing.
  14. *
  15. int
  16. rgb2cmap(int cr, int cg, int cb)
  17. {
  18. int r, g, b, v, cv;
  19. if(cr < 0)
  20. cr = 0;
  21. else if(cr > 255)
  22. cr = 255;
  23. if(cg < 0)
  24. cg = 0;
  25. else if(cg > 255)
  26. cg = 255;
  27. if(cb < 0)
  28. cb = 0;
  29. else if(cb > 255)
  30. cb = 255;
  31. r = cr>>6;
  32. g = cg>>6;
  33. b = cb>>6;
  34. cv = cr;
  35. if(cg > cv)
  36. cv = cg;
  37. if(cb > cv)
  38. cv = cb;
  39. v = (cv>>4)&3;
  40. return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15));
  41. }
  42. */
  43. int
  44. rgb2cmap(int cr, int cg, int cb)
  45. {
  46. int i, r, g, b, sq;
  47. ulong rgb;
  48. int best, bestsq;
  49. best = 0;
  50. bestsq = 0x7FFFFFFF;
  51. for(i=0; i<256; i++){
  52. rgb = cmap2rgb(i);
  53. r = (rgb>>16) & 0xFF;
  54. g = (rgb>>8) & 0xFF;
  55. b = (rgb>>0) & 0xFF;
  56. sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb);
  57. if(sq < bestsq){
  58. bestsq = sq;
  59. best = i;
  60. }
  61. }
  62. return best;
  63. }
  64. int
  65. cmap2rgb(int c)
  66. {
  67. int j, num, den, r, g, b, v, rgb;
  68. r = c>>6;
  69. v = (c>>4)&3;
  70. j = (c-v+r)&15;
  71. g = j>>2;
  72. b = j&3;
  73. den=r;
  74. if(g>den)
  75. den=g;
  76. if(b>den)
  77. den=b;
  78. if(den==0) {
  79. v *= 17;
  80. rgb = (v<<16)|(v<<8)|v;
  81. }
  82. else{
  83. num=17*(4*den+v);
  84. rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den);
  85. }
  86. return rgb;
  87. }
  88. int
  89. cmap2rgba(int c)
  90. {
  91. return (cmap2rgb(c)<<8)|0xFF;
  92. }