totruecolor.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <draw.h>
  5. #include "imagefile.h"
  6. enum {
  7. c1 = 2871, /* 1.402 * 2048 */
  8. c2 = 705, /* 0.34414 * 2048 */
  9. c3 = 1463, /* 0.71414 * 2048 */
  10. c4 = 3629, /* 1.772 * 2048 */
  11. };
  12. Rawimage*
  13. totruecolor(Rawimage *i, int chandesc)
  14. {
  15. int j, k;
  16. Rawimage *im;
  17. char err[ERRMAX];
  18. uchar *rp, *gp, *bp, *cmap, *inp, *outp, cmap1[3*256];
  19. int r, g, b, Y, Cr, Cb;
  20. if(chandesc!=CY && chandesc!=CRGB24)
  21. return _remaperror("remap: can't convert to chandesc %d", chandesc);
  22. err[0] = '\0';
  23. errstr(err, sizeof err); /* throw it away */
  24. im = malloc(sizeof(Rawimage));
  25. if(im == nil)
  26. return nil;
  27. memset(im, 0, sizeof(Rawimage));
  28. if(chandesc == CY)
  29. im->chanlen = i->chanlen;
  30. else
  31. im->chanlen = 3*i->chanlen;
  32. im->chandesc = chandesc;
  33. im->chans[0] = malloc(im->chanlen);
  34. if(im->chans[0] == nil){
  35. free(im);
  36. return nil;
  37. }
  38. im->r = i->r;
  39. im->nchans = 1;
  40. cmap = i->cmap;
  41. outp = im->chans[0];
  42. switch(i->chandesc){
  43. default:
  44. return _remaperror("remap: can't recognize channel type %d", i->chandesc);
  45. case CY:
  46. if(i->nchans != 1)
  47. return _remaperror("remap: Y image has %d chans", i->nchans);
  48. if(chandesc == CY){
  49. memmove(im->chans[0], i->chans[0], i->chanlen);
  50. break;
  51. }
  52. /* convert to three color */
  53. inp = i->chans[0];
  54. for(j=0; j<i->chanlen; j++){
  55. k = *inp++;
  56. *outp++ = k;
  57. *outp++ = k;
  58. *outp++ = k;
  59. }
  60. break;
  61. case CRGB1:
  62. if(cmap == nil)
  63. return _remaperror("remap: image has no color map");
  64. if(i->nchans != 1)
  65. return _remaperror("remap: can't handle nchans %d", i->nchans);
  66. for(j=1; j<=8; j++)
  67. if(i->cmaplen == 3*(1<<j))
  68. break;
  69. if(j > 8)
  70. return _remaperror("remap: can't do colormap size 3*%d", i->cmaplen/3);
  71. if(i->cmaplen != 3*256){
  72. /* to avoid a range check in loop below, make a full-size cmap */
  73. memmove(cmap1, cmap, i->cmaplen);
  74. cmap = cmap1;
  75. }
  76. inp = i->chans[0];
  77. if(chandesc == CY){
  78. for(j=0; j<i->chanlen; j++){
  79. k = *inp++;
  80. r = cmap[3*k+2];
  81. g = cmap[3*k+1];
  82. b = cmap[3*k+0];
  83. r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
  84. *outp++ = r;
  85. }
  86. }else{
  87. for(j=0; j<i->chanlen; j++){
  88. k = *inp++;
  89. *outp++ = cmap[3*k+2];
  90. *outp++ = cmap[3*k+1];
  91. *outp++ = cmap[3*k+0];
  92. }
  93. }
  94. break;
  95. case CRGB:
  96. if(i->nchans != 3)
  97. return _remaperror("remap: can't handle nchans %d", i->nchans);
  98. rp = i->chans[0];
  99. gp = i->chans[1];
  100. bp = i->chans[2];
  101. if(chandesc == CY){
  102. for(j=0; j<i->chanlen; j++){
  103. r = *bp++;
  104. g = *gp++;
  105. b = *rp++;
  106. r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
  107. *outp++ = r;
  108. }
  109. }else
  110. for(j=0; j<i->chanlen; j++){
  111. *outp++ = *bp++;
  112. *outp++ = *gp++;
  113. *outp++ = *rp++;
  114. }
  115. break;
  116. case CYCbCr:
  117. if(i->nchans != 3)
  118. return _remaperror("remap: can't handle nchans %d", i->nchans);
  119. rp = i->chans[0];
  120. gp = i->chans[1];
  121. bp = i->chans[2];
  122. for(j=0; j<i->chanlen; j++){
  123. Y = *rp++ << 11;
  124. Cb = *gp++ - 128;
  125. Cr = *bp++ - 128;
  126. r = (Y+c1*Cr) >> 11;
  127. g = (Y-c2*Cb-c3*Cr) >> 11;
  128. b = (Y+c4*Cb) >> 11;
  129. if(r < 0)
  130. r = 0;
  131. if(r > 255)
  132. r = 255;
  133. if(g < 0)
  134. g = 0;
  135. if(g > 255)
  136. g = 255;
  137. if(b < 0)
  138. b = 0;
  139. if(b > 255)
  140. b = 255;
  141. if(chandesc == CY){
  142. r = (2125*r + 7154*g + 721*b)/10000;
  143. *outp++ = r;
  144. }else{
  145. *outp++ = b;
  146. *outp++ = g;
  147. *outp++ = r;
  148. }
  149. }
  150. break;
  151. }
  152. return im;
  153. }