Blame tools/ycbcr.c

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