Hi
this patch adds
YCbCr ITU-R Rec. BT.470-2 (== BT.624-4 seems to be == BT.601) and
YCbCr ITU-R Rec. BT.709
compose & decompose support
i would have added YUV & YIQ too but this isnt possible as the UV & IQ values
can be negative, and when scaled & shifted into unsigned range then YUV =
YCbCr ITU-R Rec. BT.470-2 anyway
the correct YCbCr uses the luminance range from 16-235 & chrominance 16-240,
this is supported now :), i allso added support for 0-255 variants, i dunno
if the 0-255 variant is usefull
btw, the rgb <-> YCbCr equations are from the 2 color faqs
Michael
Index: compose.c
===================================================================
RCS file: /cvs/gnome/gimp/plug-ins/common/compose.c,v
retrieving revision 1.32
diff -u -r1.32 compose.c
--- compose.c 29 Dec 2001 13:18:46 -0000 1.32
+++ compose.c 21 Oct 2002 19:41:09 -0000
@@ -81,6 +81,10 @@
static void compose_hsv (guchar **src, gint *incr, gint numpix, guchar *dst);
static void compose_cmy (guchar **src, gint *incr, gint numpix, guchar *dst);
static void compose_cmyk (guchar **src, gint *incr, gint numpix, guchar *dst);
+static void compose_ycbcr470 (guchar **src, gint *incr, gint numpix, guchar *dst);
+static void compose_ycbcr709 (guchar **src, gint *incr, gint numpix, guchar *dst);
+static void compose_ycbcr470f(guchar **src, gint *incr, gint numpix, guchar *dst);
+static void compose_ycbcr709f(guchar **src, gint *incr, gint numpix, guchar *dst);
static gint compose_dialog (gchar *compose_type,
gint32 drawable_ID);
@@ -136,7 +140,27 @@
{ N_("CMYK"), 4, { N_("Cyan:"),
N_("Magenta:"),
N_("Yellow:"),
- N_("Black:") }, N_("cmyk-compose"), compose_cmyk }
+ N_("Black:") }, N_("cmyk-compose"), compose_cmyk },
+ { N_("YCbCr_ITU_R470"),
+ 3, { N_("Y:"),
+ N_("Cb:"),
+ N_("Cr:"),
+ CHNL_NA }, N_("ycbcr470-compose"), compose_ycbcr470 },
+ { N_("YCbCr_ITU_R709"),
+ 3, { N_("Y:"),
+ N_("Cb:"),
+ N_("Cr:"),
+ CHNL_NA }, N_("ycbcr709-compose"), compose_ycbcr709 },
+ { N_("YCbCr_ITU_R470_256"),
+ 3, { N_("Y:"),
+ N_("Cb:"),
+ N_("Cr:"),
+ CHNL_NA }, N_("ycbcr470F-compose"), compose_ycbcr470f },
+ { N_("YCbCr_ITU_R709_256"),
+ 3, { N_("Y:"),
+ N_("Cb:"),
+ N_("Cr:"),
+ CHNL_NA }, N_("ycbcr709F-compose"), compose_ycbcr709f },
};
#define MAX_COMPOSE_TYPES (G_N_ELEMENTS (compose_dsc))
@@ -735,6 +759,164 @@
magenta_src += magenta_incr;
yellow_src += yellow_incr;
black_src += black_incr;
+ }
+}
+
+/* these are here so the code is more readable and we can use
+ the standart values instead of some scaled and rounded fixpoint values */
+#define FIX(a) ((int)((a)*256.0*256.0 + 0.5))
+#define FIXY(a) ((int)((a)*256.0*256.0*255.0/219.0 + 0.5))
+#define FIXC(a) ((int)((a)*256.0*256.0*255.0/224.0 + 0.5))
+
+
+static void
+compose_ycbcr470 (guchar **src,
+ gint *incr_src,
+ gint numpix,
+ guchar *dst)
+{
+ register guchar *y_src = src[0];
+ register guchar *cb_src = src[1];
+ register guchar *cr_src = src[2];
+ register guchar *rgb_dst = dst;
+ register gint count = numpix;
+ gint y_incr = incr_src[0], cb_incr = incr_src[1], cr_incr = incr_src[2];
+
+ while (count-- > 0)
+ {
+ int r,g,b,y,cb,cr;
+ y = *y_src - 16;
+ cb= *cb_src - 128;
+ cr= *cr_src - 128;
+ y_src += y_incr;
+ cb_src += cb_incr;
+ cr_src += cr_incr;
+
+ r = (FIXY(1.0)*y + FIXC(1.4022)*cr + FIX(0.5))>>16;
+ g = (FIXY(1.0)*y - FIXC(0.3456)*cb - FIXC(0.7145)*cr + FIX(0.5))>>16;
+ b = (FIXY(1.0)*y + FIXC(1.7710)*cb + FIX(0.5))>>16;
+
+ if(((unsigned)r) > 255) r = ((r>>10)&255)^255;
+ if(((unsigned)g) > 255) g = ((g>>10)&255)^255;
+ if(((unsigned)b) > 255) b = ((b>>10)&255)^255;
+
+ *(rgb_dst++) = r;
+ *(rgb_dst++) = g;
+ *(rgb_dst++) = b;
+ }
+}
+
+
+static void
+compose_ycbcr709 (guchar **src,
+ gint *incr_src,
+ gint numpix,
+ guchar *dst)
+{
+ register guchar *y_src = src[0];
+ register guchar *cb_src = src[1];
+ register guchar *cr_src = src[2];
+ register guchar *rgb_dst = dst;
+ register gint count = numpix;
+ gint y_incr = incr_src[0], cb_incr = incr_src[1], cr_incr = incr_src[2];
+
+ while (count-- > 0)
+ {
+ int r,g,b,y,cb,cr;
+ y = *y_src - 16;
+ cb= *cb_src - 128;
+ cr= *cr_src - 128;
+ y_src += y_incr;
+ cb_src += cb_incr;
+ cr_src += cr_incr;
+
+ r = (FIXY(1.0)*y + FIXC(1.5748)*cr + FIX(0.5))>>16;
+ g = (FIXY(1.0)*y - FIXC(0.1873)*cb - FIXC(0.4681)*cr + FIX(0.5))>>16;
+ b = (FIXY(1.0)*y + FIXC(1.8556)*cb + FIX(0.5))>>16;
+
+ if(((unsigned)r) > 255) r = ((r>>10)&255)^255;
+ if(((unsigned)g) > 255) g = ((g>>10)&255)^255;
+ if(((unsigned)b) > 255) b = ((b>>10)&255)^255;
+
+ *(rgb_dst++) = r;
+ *(rgb_dst++) = g;
+ *(rgb_dst++) = b;
+ }
+}
+
+
+static void
+compose_ycbcr470f (guchar **src,
+ gint *incr_src,
+ gint numpix,
+ guchar *dst)
+{
+ register guchar *y_src = src[0];
+ register guchar *cb_src = src[1];
+ register guchar *cr_src = src[2];
+ register guchar *rgb_dst = dst;
+ register gint count = numpix;
+ gint y_incr = incr_src[0], cb_incr = incr_src[1], cr_incr = incr_src[2];
+
+ while (count-- > 0)
+ {
+ int r,g,b,y,cb,cr;
+ y = *y_src;
+ cb= *cb_src - 128;
+ cr= *cr_src - 128;
+ y_src += y_incr;
+ cb_src += cb_incr;
+ cr_src += cr_incr;
+
+ r = (FIX(1.0)*y + FIX(1.4022)*cr + FIX(0.5))>>16;
+ g = (FIX(1.0)*y - FIX(0.3456)*cb - FIX(0.7145)*cr + FIX(0.5))>>16;
+ b = (FIX(1.0)*y + FIX(1.7710)*cb + FIX(0.5))>>16;
+
+ if(((unsigned)r) > 255) r = ((r>>10)&255)^255;
+ if(((unsigned)g) > 255) g = ((g>>10)&255)^255;
+ if(((unsigned)b) > 255) b = ((b>>10)&255)^255;
+
+ *(rgb_dst++) = r;
+ *(rgb_dst++) = g;
+ *(rgb_dst++) = b;
+ }
+}
+
+
+static void
+compose_ycbcr709f (guchar **src,
+ gint *incr_src,
+ gint numpix,
+ guchar *dst)
+{
+ register guchar *y_src = src[0];
+ register guchar *cb_src = src[1];
+ register guchar *cr_src = src[2];
+ register guchar *rgb_dst = dst;
+ register gint count = numpix;
+ gint y_incr = incr_src[0], cb_incr = incr_src[1], cr_incr = incr_src[2];
+
+ while (count-- > 0)
+ {
+ int r,g,b,y,cb,cr;
+ y = *y_src;
+ cb= *cb_src - 128;
+ cr= *cr_src - 128;
+ y_src += y_incr;
+ cb_src += cb_incr;
+ cr_src += cr_incr;
+
+ r = (FIX(1.0)*y + FIX(1.5748)*cr + FIX(0.5))>>16;
+ g = (FIX(1.0)*y - FIX(0.1873)*cb - FIX(0.4681)*cr + FIX(0.5))>>16;
+ b = (FIX(1.0)*y + FIX(1.8556)*cb + FIX(0.5))>>16;
+
+ if(((unsigned)r) > 255) r = ((r>>10)&255)^255;
+ if(((unsigned)g) > 255) g = ((g>>10)&255)^255;
+ if(((unsigned)b) > 255) b = ((b>>10)&255)^255;
+
+ *(rgb_dst++) = r;
+ *(rgb_dst++) = g;
+ *(rgb_dst++) = b;
}
}
Index: decompose.c
===================================================================
RCS file: /cvs/gnome/gimp/plug-ins/common/decompose.c,v
retrieving revision 1.31
diff -u -r1.31 decompose.c
--- decompose.c 4 Aug 2002 14:37:30 -0000 1.31
+++ decompose.c 21 Oct 2002 19:41:09 -0000
@@ -88,6 +88,10 @@
static void extract_cyank (guchar *src, gint bpp, gint numpix, guchar **dst);
static void extract_magentak (guchar *src, gint bpp, gint numpix, guchar **dst);
static void extract_yellowk (guchar *src, gint bpp, gint numpix, guchar **dst);
+static void extract_ycbcr470 (guchar *src, gint bpp, gint numpix, guchar **dst);
+static void extract_ycbcr709 (guchar *src, gint bpp, gint numpix, guchar **dst);
+static void extract_ycbcr470f(guchar *src, gint bpp, gint numpix, guchar **dst);
+static void extract_ycbcr709f(guchar *src, gint bpp, gint numpix, guchar **dst);
static gint decompose_dialog (void);
static void decompose_ok_callback (GtkWidget *widget,
@@ -140,7 +144,23 @@
{ N_("Cyan_K"), FALSE, 1, { N_("cyan_k") }, extract_cyank },
{ N_("Magenta_K"), FALSE, 1, { N_("magenta_k") }, extract_magentak },
{ N_("Yellow_K"), FALSE, 1, { N_("yellow_k") }, extract_yellowk },
- { N_("Alpha"), TRUE, 1, { N_("alpha") }, extract_alpha }
+ { N_("Alpha"), TRUE, 1, { N_("alpha") }, extract_alpha },
+ { N_("YCbCr_ITU_R470"),
+ TRUE, 3, { N_("y"),
+ N_("cb"),
+ N_("cr") }, extract_ycbcr470 },
+ { N_("YCbCr_ITU_R709"),
+ TRUE, 3, { N_("y"),
+ N_("cb"),
+ N_("cr") }, extract_ycbcr709 },
+ { N_("YCbCr_ITU_R470_256"),
+ TRUE, 3, { N_("y"),
+ N_("cb"),
+ N_("cr") }, extract_ycbcr470f },
+ { N_("YCbCr_ITU_R709_256"),
+ TRUE, 3, { N_("y"),
+ N_("cb"),
+ N_("cr") }, extract_ycbcr709f },
};
/* Number of types of extractions */
@@ -887,6 +907,126 @@
*yellow_dst -= k;
yellow_dst++;
+ rgb_src += offset;
+ }
+}
+
+/* these are here so the code is more readable and we can use
+ the standart values instead of some scaled and rounded fixpoint values */
+#define FIX(a) ((int)((a)*256.0*256.0 + 0.5))
+#define FIXY(a) ((int)((a)*256.0*256.0*219.0/255.0 + 0.5))
+#define FIXC(a) ((int)((a)*256.0*256.0*224.0/255.0 + 0.5))
+
+static void
+extract_ycbcr470 (guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register guchar *rgb_src = src;
+ register guchar *y_dst = dst[0];
+ register guchar *cb_dst = dst[1];
+ register guchar *cr_dst = dst[2];
+ register gint count = numpix, offset = bpp-3;
+
+ while (count-- > 0)
+ {
+ register int r, g, b;
+ r= *(rgb_src++);
+ g= *(rgb_src++);
+ b= *(rgb_src++);
+ *(y_dst++) = ( FIXY(0.2989)*r + FIXY(0.5866)*g + FIXY(0.1145)*b + FIX( 16.5))>>16;
+ *(cb_dst++) = (-FIXC(0.1688)*r - FIXC(0.3312)*g + FIXC(0.5000)*b + FIX(128.5))>>16;
+ *(cr_dst++) = ( FIXC(0.5000)*r - FIXC(0.4184)*g - FIXC(0.0816)*b + FIX(128.5))>>16;
+
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_ycbcr709 (guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register guchar *rgb_src = src;
+ register guchar *y_dst = dst[0];
+ register guchar *cb_dst = dst[1];
+ register guchar *cr_dst = dst[2];
+ register gint count = numpix, offset = bpp-3;
+
+ while (count-- > 0)
+ {
+ register int r, g, b;
+ r= *(rgb_src++);
+ g= *(rgb_src++);
+ b= *(rgb_src++);
+ *(y_dst++) = ( FIXY(0.2126)*r + FIXY(0.7152)*g + FIXY(0.0722)*b + FIX( 16.5))>>16;
+ *(cb_dst++) = (-FIXC(0.1150)*r - FIXC(0.3860)*g + FIXC(0.5000)*b + FIX(128.5))>>16;
+ *(cr_dst++) = ( FIXC(0.5000)*r - FIXC(0.4540)*g - FIXC(0.0460)*b + FIX(128.5))>>16;
+
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_ycbcr470f (guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register guchar *rgb_src = src;
+ register guchar *y_dst = dst[0];
+ register guchar *cb_dst = dst[1];
+ register guchar *cr_dst = dst[2];
+ register gint count = numpix, offset = bpp-3;
+
+ while (count-- > 0)
+ {
+ register int r, g, b, cb, cr;
+ r= *(rgb_src++);
+ g= *(rgb_src++);
+ b= *(rgb_src++);
+ *(y_dst++ ) = ( FIX(0.2989)*r + FIX(0.5866)*g + FIX(0.1145)*b + FIX( 0.5))>>16;
+ cb = (-FIX(0.1688)*r - FIX(0.3312)*g + FIX(0.5000)*b + FIX(128.5))>>16;
+ cr = ( FIX(0.5000)*r - FIX(0.4184)*g - FIX(0.0816)*b + FIX(128.5))>>16;
+ if(cb>255) cb=255;
+ if(cr>255) cr=255;
+ *(cb_dst++) = cb;
+ *(cr_dst++) = cr;
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_ycbcr709f (guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register guchar *rgb_src = src;
+ register guchar *y_dst = dst[0];
+ register guchar *cb_dst = dst[1];
+ register guchar *cr_dst = dst[2];
+ register gint count = numpix, offset = bpp-3;
+
+ while (count-- > 0)
+ {
+ register int r, g, b, cb, cr;
+ r= *(rgb_src++);
+ g= *(rgb_src++);
+ b= *(rgb_src++);
+ *(y_dst++) = ( FIX(0.2126)*r + FIX(0.7152)*g + FIX(0.0722)*b + FIX( 0.5))>>16;
+ cb = (-FIX(0.1150)*r - FIX(0.3860)*g + FIX(0.5000)*b + FIX(128.5))>>16;
+ cr = ( FIX(0.5000)*r - FIX(0.4540)*g - FIX(0.0460)*b + FIX(128.5))>>16;
+ if(cb>255) cb=255;
+ if(cr>255) cr=255;
+ *(cb_dst++) = cb;
+ *(cr_dst++) = cr;
+
rgb_src += offset;
}
}