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