|
roentgen |
b75cab |
float ycbcrCoeffs[3] = { .299, .587, .114 };
|
|
roentgen |
b75cab |
/* default coding range is CCIR Rec 601-1 with no headroom/footroom */
|
|
roentgen |
b75cab |
unsigned long refBlackWhite[6] = { 0, 255, 128, 255, 128, 255 };
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#define LumaRed ycbcrCoeffs[0]
|
|
roentgen |
b75cab |
#define LumaGreen ycbcrCoeffs[1]
|
|
roentgen |
b75cab |
#define LumaBlue ycbcrCoeffs[2]
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
long eRtotal = 0;
|
|
roentgen |
b75cab |
long eGtotal = 0;
|
|
roentgen |
b75cab |
long eBtotal = 0;
|
|
roentgen |
b75cab |
long preveRtotal = 0;
|
|
roentgen |
b75cab |
long preveGtotal = 0;
|
|
roentgen |
b75cab |
long preveBtotal = 0;
|
|
roentgen |
b75cab |
unsigned long AbseRtotal = 0;
|
|
roentgen |
b75cab |
unsigned long AbseGtotal = 0;
|
|
roentgen |
b75cab |
unsigned long AbseBtotal = 0;
|
|
roentgen |
b75cab |
unsigned long eCodes = 0;
|
|
roentgen |
b75cab |
unsigned long preveCodes = 0;
|
|
roentgen |
b75cab |
unsigned long eBits = 0;
|
|
roentgen |
b75cab |
unsigned long preveBits = 0;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static void setupLumaTables();
|
|
roentgen |
b75cab |
static int abs(int v) { return (v < 0 ? -v : v); }
|
|
roentgen |
b75cab |
static double pct(int v,double range) { return (v*100. / range); }
|
|
roentgen |
b75cab |
static void check(int R, int G, int B);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
float D1, D2;
|
|
roentgen |
b75cab |
float D3, D4;
|
|
roentgen |
b75cab |
float D5, D6;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
main(int argc, char** argv)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
int R, G, B;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (argc > 1) {
|
|
roentgen |
b75cab |
refBlackWhite[0] = 16;
|
|
roentgen |
b75cab |
refBlackWhite[1] = 235;
|
|
roentgen |
b75cab |
refBlackWhite[2] = 128;
|
|
roentgen |
b75cab |
refBlackWhite[3] = 240;
|
|
roentgen |
b75cab |
refBlackWhite[4] = 128;
|
|
roentgen |
b75cab |
refBlackWhite[5] = 240;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
D3 = 2 - 2*LumaRed;
|
|
roentgen |
b75cab |
D4 = 2 - 2*LumaBlue;
|
|
roentgen |
b75cab |
D1 = 1. / D3;
|
|
roentgen |
b75cab |
D2 = 1. / D4;
|
|
roentgen |
b75cab |
D5 = D3*LumaRed / LumaGreen;
|
|
roentgen |
b75cab |
D6 = D4*LumaBlue / LumaGreen;
|
|
roentgen |
b75cab |
setupLumaTables();
|
|
roentgen |
b75cab |
for (R = 0; R < 256; R++) {
|
|
roentgen |
b75cab |
for (G = 0; G < 256; G++)
|
|
roentgen |
b75cab |
for (B = 0; B < 256; B++)
|
|
roentgen |
b75cab |
check(R, G, B);
|
|
roentgen |
b75cab |
printf("[%3u] c %u/%u b %u/%u (R %u/%d/%u G %u/%d/%u B %u/%d/%u)\n"
|
|
roentgen |
b75cab |
, R
|
|
roentgen |
b75cab |
, eCodes - preveCodes, eCodes
|
|
roentgen |
b75cab |
, eBits - preveBits, eBits
|
|
roentgen |
b75cab |
, abs(AbseRtotal - preveRtotal), eRtotal , AbseRtotal
|
|
roentgen |
b75cab |
, abs(AbseGtotal - preveGtotal), eGtotal , AbseGtotal
|
|
roentgen |
b75cab |
, abs(AbseBtotal - preveBtotal), eBtotal , AbseBtotal
|
|
roentgen |
b75cab |
);
|
|
roentgen |
b75cab |
preveRtotal = AbseRtotal;
|
|
roentgen |
b75cab |
preveGtotal = AbseGtotal;
|
|
roentgen |
b75cab |
preveBtotal = AbseBtotal;
|
|
roentgen |
b75cab |
preveCodes = eCodes;
|
|
roentgen |
b75cab |
preveBits = eBits;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
printf("%u total codes\n", 256*256*256);
|
|
roentgen |
b75cab |
printf("total error: %u codes %u bits (R %d/%u G %d/%u B %d/%u)\n"
|
|
roentgen |
b75cab |
, eCodes
|
|
roentgen |
b75cab |
, eBits
|
|
roentgen |
b75cab |
, eRtotal , AbseRtotal
|
|
roentgen |
b75cab |
, eGtotal , AbseGtotal
|
|
roentgen |
b75cab |
, eBtotal , AbseBtotal
|
|
roentgen |
b75cab |
);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
float *lumaRed;
|
|
roentgen |
b75cab |
float *lumaGreen;
|
|
roentgen |
b75cab |
float *lumaBlue;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static float*
|
|
roentgen |
b75cab |
setupLuma(float c)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
float *v = (float *)_TIFFmalloc(256 * sizeof (float));
|
|
roentgen |
b75cab |
int i;
|
|
roentgen |
b75cab |
for (i = 0; i < 256; i++)
|
|
roentgen |
b75cab |
v[i] = c * i;
|
|
roentgen |
b75cab |
return (v);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static void
|
|
roentgen |
b75cab |
setupLumaTables(void)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
lumaRed = setupLuma(LumaRed);
|
|
roentgen |
b75cab |
lumaGreen = setupLuma(LumaGreen);
|
|
roentgen |
b75cab |
lumaBlue = setupLuma(LumaBlue);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static unsigned
|
|
roentgen |
b75cab |
V2Code(float f, unsigned long RB, unsigned long RW, int CR)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
unsigned int c = (unsigned int)((((f)*(RW-RB)/CR)+RB)+.5);
|
|
roentgen |
b75cab |
return (c > 255 ? 255 : c);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#define Code2V(c, RB, RW, CR) ((((c)-(int)RB)*(float)CR)/(float)(RW-RB))
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#define CLAMP(f,min,max) \
|
|
roentgen |
b75cab |
(int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
check(int R, int G, int B)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
float Y, Cb, Cr;
|
|
roentgen |
b75cab |
int iY, iCb, iCr;
|
|
roentgen |
b75cab |
float rY, rCb, rCr;
|
|
roentgen |
b75cab |
float rR, rG, rB;
|
|
roentgen |
b75cab |
int eR, eG, eB;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
Y = lumaRed[R] + lumaGreen[G] + lumaBlue[B];
|
|
roentgen |
b75cab |
Cb = (B - Y)*D2;
|
|
roentgen |
b75cab |
Cr = (R - Y)*D1;
|
|
roentgen |
b75cab |
iY = V2Code(Y, refBlackWhite[0], refBlackWhite[1], 255);
|
|
roentgen |
b75cab |
iCb = V2Code(Cb, refBlackWhite[2], refBlackWhite[3], 127);
|
|
roentgen |
b75cab |
iCr = V2Code(Cr, refBlackWhite[4], refBlackWhite[5], 127);
|
|
roentgen |
b75cab |
rCb = Code2V(iCb, refBlackWhite[2], refBlackWhite[3], 127);
|
|
roentgen |
b75cab |
rCr = Code2V(iCr, refBlackWhite[4], refBlackWhite[5], 127);
|
|
roentgen |
b75cab |
rY = Code2V(iY, refBlackWhite[0], refBlackWhite[1], 255);
|
|
roentgen |
b75cab |
rR = rY + rCr*D3;
|
|
roentgen |
b75cab |
rB = rY + rCb*D4;
|
|
roentgen |
b75cab |
rG = rY - rCb*D6 - rCr*D5;
|
|
roentgen |
b75cab |
eR = R - CLAMP(rR,0,255);
|
|
roentgen |
b75cab |
eG = G - CLAMP(rG,0,255);
|
|
roentgen |
b75cab |
eB = B - CLAMP(rB,0,255);
|
|
roentgen |
b75cab |
if (abs(eR) > 1 || abs(eG) > 1 || abs(eB) > 1) {
|
|
roentgen |
b75cab |
printf("R %u G %u B %u", R, G, B);
|
|
roentgen |
b75cab |
printf(" Y %g Cb %g Cr %g", Y, Cb, Cr);
|
|
roentgen |
b75cab |
printf(" iY %u iCb %u iCr %u", iY, iCb, iCr);
|
|
roentgen |
b75cab |
printf("\n -> Y %g Cb %g Cr %g", rY, rCb, rCr);
|
|
roentgen |
b75cab |
printf(" R %g (%u) G %g (%u) B %g (%u) E=[%d %d %d])\n"
|
|
roentgen |
b75cab |
, rR, CLAMP(rR,0,255)
|
|
roentgen |
b75cab |
, rG, CLAMP(rG,0,255)
|
|
roentgen |
b75cab |
, rB, CLAMP(rB,0,255)
|
|
roentgen |
b75cab |
, eR, eG, eB
|
|
roentgen |
b75cab |
);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
eRtotal += eR;
|
|
roentgen |
b75cab |
eGtotal += eG;
|
|
roentgen |
b75cab |
eBtotal += eB;
|
|
roentgen |
b75cab |
AbseRtotal += abs(eR);
|
|
roentgen |
b75cab |
AbseGtotal += abs(eG);
|
|
roentgen |
b75cab |
AbseBtotal += abs(eB);
|
|
roentgen |
b75cab |
if (eR | eG | eB)
|
|
roentgen |
b75cab |
eCodes++;
|
|
roentgen |
b75cab |
eBits += abs(eR) + abs(eG) + abs(eB);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Local Variables:
|
|
roentgen |
b75cab |
* mode: c
|
|
roentgen |
b75cab |
* c-basic-offset: 8
|
|
roentgen |
b75cab |
* fill-column: 78
|
|
roentgen |
b75cab |
* End:
|
|
roentgen |
b75cab |
*/
|