[Gimp-developer] YCbCr (de)compose support [PATCH]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
     }
 }

[Index of Archives]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [GIMP for Windows]     [KDE]     [GEGL]     [Gimp's Home]     [Gimp on GUI]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux