2
0

ycbcr.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. float ycbcrCoeffs[3] = { .299, .587, .114 };
  2. /* default coding range is CCIR Rec 601-1 with no headroom/footroom */
  3. unsigned long refBlackWhite[6] = { 0, 255, 128, 255, 128, 255 };
  4. #define LumaRed ycbcrCoeffs[0]
  5. #define LumaGreen ycbcrCoeffs[1]
  6. #define LumaBlue ycbcrCoeffs[2]
  7. long eRtotal = 0;
  8. long eGtotal = 0;
  9. long eBtotal = 0;
  10. long preveRtotal = 0;
  11. long preveGtotal = 0;
  12. long preveBtotal = 0;
  13. unsigned long AbseRtotal = 0;
  14. unsigned long AbseGtotal = 0;
  15. unsigned long AbseBtotal = 0;
  16. unsigned long eCodes = 0;
  17. unsigned long preveCodes = 0;
  18. unsigned long eBits = 0;
  19. unsigned long preveBits = 0;
  20. static void setupLumaTables();
  21. static int abs(int v) { return (v < 0 ? -v : v); }
  22. static double pct(int v,double range) { return (v*100. / range); }
  23. static void check(int R, int G, int B);
  24. float D1, D2;
  25. float D3, D4;
  26. float D5, D6;
  27. int
  28. main(int argc, char** argv)
  29. {
  30. int R, G, B;
  31. if (argc > 1) {
  32. refBlackWhite[0] = 16;
  33. refBlackWhite[1] = 235;
  34. refBlackWhite[2] = 128;
  35. refBlackWhite[3] = 240;
  36. refBlackWhite[4] = 128;
  37. refBlackWhite[5] = 240;
  38. }
  39. D3 = 2 - 2*LumaRed;
  40. D4 = 2 - 2*LumaBlue;
  41. D1 = 1. / D3;
  42. D2 = 1. / D4;
  43. D5 = D3*LumaRed / LumaGreen;
  44. D6 = D4*LumaBlue / LumaGreen;
  45. setupLumaTables();
  46. for (R = 0; R < 256; R++) {
  47. for (G = 0; G < 256; G++)
  48. for (B = 0; B < 256; B++)
  49. check(R, G, B);
  50. printf("[%3u] c %u/%u b %u/%u (R %u/%d/%u G %u/%d/%u B %u/%d/%u)\n"
  51. , R
  52. , eCodes - preveCodes, eCodes
  53. , eBits - preveBits, eBits
  54. , abs(AbseRtotal - preveRtotal), eRtotal , AbseRtotal
  55. , abs(AbseGtotal - preveGtotal), eGtotal , AbseGtotal
  56. , abs(AbseBtotal - preveBtotal), eBtotal , AbseBtotal
  57. );
  58. preveRtotal = AbseRtotal;
  59. preveGtotal = AbseGtotal;
  60. preveBtotal = AbseBtotal;
  61. preveCodes = eCodes;
  62. preveBits = eBits;
  63. }
  64. printf("%u total codes\n", 256*256*256);
  65. printf("total error: %u codes %u bits (R %d/%u G %d/%u B %d/%u)\n"
  66. , eCodes
  67. , eBits
  68. , eRtotal , AbseRtotal
  69. , eGtotal , AbseGtotal
  70. , eBtotal , AbseBtotal
  71. );
  72. return (0);
  73. }
  74. float *lumaRed;
  75. float *lumaGreen;
  76. float *lumaBlue;
  77. static float*
  78. setupLuma(float c)
  79. {
  80. float *v = (float *)_TIFFmalloc(256 * sizeof (float));
  81. int i;
  82. for (i = 0; i < 256; i++)
  83. v[i] = c * i;
  84. return (v);
  85. }
  86. static void
  87. setupLumaTables(void)
  88. {
  89. lumaRed = setupLuma(LumaRed);
  90. lumaGreen = setupLuma(LumaGreen);
  91. lumaBlue = setupLuma(LumaBlue);
  92. }
  93. static unsigned
  94. V2Code(float f, unsigned long RB, unsigned long RW, int CR)
  95. {
  96. unsigned int c = (unsigned int)((((f)*(RW-RB)/CR)+RB)+.5);
  97. return (c > 255 ? 255 : c);
  98. }
  99. #define Code2V(c, RB, RW, CR) ((((c)-(int)RB)*(float)CR)/(float)(RW-RB))
  100. #define CLAMP(f,min,max) \
  101. (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
  102. static
  103. void
  104. check(int R, int G, int B)
  105. {
  106. float Y, Cb, Cr;
  107. int iY, iCb, iCr;
  108. float rY, rCb, rCr;
  109. float rR, rG, rB;
  110. int eR, eG, eB;
  111. Y = lumaRed[R] + lumaGreen[G] + lumaBlue[B];
  112. Cb = (B - Y)*D2;
  113. Cr = (R - Y)*D1;
  114. iY = V2Code(Y, refBlackWhite[0], refBlackWhite[1], 255);
  115. iCb = V2Code(Cb, refBlackWhite[2], refBlackWhite[3], 127);
  116. iCr = V2Code(Cr, refBlackWhite[4], refBlackWhite[5], 127);
  117. rCb = Code2V(iCb, refBlackWhite[2], refBlackWhite[3], 127);
  118. rCr = Code2V(iCr, refBlackWhite[4], refBlackWhite[5], 127);
  119. rY = Code2V(iY, refBlackWhite[0], refBlackWhite[1], 255);
  120. rR = rY + rCr*D3;
  121. rB = rY + rCb*D4;
  122. rG = rY - rCb*D6 - rCr*D5;
  123. eR = R - CLAMP(rR,0,255);
  124. eG = G - CLAMP(rG,0,255);
  125. eB = B - CLAMP(rB,0,255);
  126. if (abs(eR) > 1 || abs(eG) > 1 || abs(eB) > 1) {
  127. printf("R %u G %u B %u", R, G, B);
  128. printf(" Y %g Cb %g Cr %g", Y, Cb, Cr);
  129. printf(" iY %u iCb %u iCr %u", iY, iCb, iCr);
  130. printf("\n -> Y %g Cb %g Cr %g", rY, rCb, rCr);
  131. printf(" R %g (%u) G %g (%u) B %g (%u) E=[%d %d %d])\n"
  132. , rR, CLAMP(rR,0,255)
  133. , rG, CLAMP(rG,0,255)
  134. , rB, CLAMP(rB,0,255)
  135. , eR, eG, eB
  136. );
  137. }
  138. eRtotal += eR;
  139. eGtotal += eG;
  140. eBtotal += eB;
  141. AbseRtotal += abs(eR);
  142. AbseGtotal += abs(eG);
  143. AbseBtotal += abs(eB);
  144. if (eR | eG | eB)
  145. eCodes++;
  146. eBits += abs(eR) + abs(eG) + abs(eB);
  147. }
  148. /*
  149. * Local Variables:
  150. * mode: c
  151. * c-basic-offset: 8
  152. * fill-column: 78
  153. * End:
  154. */