Porting the decompose/compose plugin
This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.
This is a read-only list on gimpusers.com so this discussion thread is read-only, too.
Porting the decompose/compose plugin | Alexander Hämmerle | 04 Dec 20:09 |
Porting the decompose/compose plugin
Hi,
recently I recommenced porting the decompose/compose plugin to babl and so far
nearly everything's fine. The only exception consists in the YCbCr-colorspace-
algorithms which are causing some headache. Below I post the original code and
what I've done with it. The conversion-problems are illustrated in the
screenshots respectively (tried to keep them small, where do you normally link
things like that?).
I think the errors in the conversion are kind of a type-casting problem. But
until now I couldn't come up with a right way to port the algorithm. Any ideas
about what is the problem are appreciated!
Thx, Alex
First the original code as it resides in decompose.c.
---> gimp/plug-ins/common/decompose.c:
#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 (const guchar *src,
gint bpp,
gint numpix,
guchar **dst)
{
register const 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;
}
}
Here is how I ported the conversion to a babl-extensions and substituted the code in decompose.c
---> gimp/plug-ins/common/decompose.c:
static void
extract_ycbcr470 (const guchar *src,
gint bpp_src,
gint numpix,
guchar **dst)
{
register const 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;
register const int bpp_dst = 3;
gdouble *ycbcr470_buffer;
const Babl *rgb = babl_format ("RGB u8"); const Babl *rgba = babl_format ("RGBA u8"); const Babl *ycbcr470 = babl_format ("YCbCr470 double"); const Babl *rgb_to_ycbcr470 = babl_fish (rgb, ycbcr470); const Babl *rgba_to_ycbcr470 = babl_fish (rgba, ycbcr470);
ycbcr470_buffer = malloc (numpix * bpp_dst * sizeof (gdouble));
if (bpp_src == 4)
{
babl_process (rgba_to_ycbcr470, rgb_src, ycbcr470_buffer, numpix);
}
else
{
babl_process (rgb_to_ycbcr470, rgb_src, ycbcr470_buffer, numpix);
}
while (count--)
{
*y_dst++ = (guchar) (ycbcr470_buffer[0] * 255.0);
*cb_dst++ = (guchar) (ycbcr470_buffer[1] * 255.0);
*cr_dst++ = (guchar) (ycbcr470_buffer[2] * 255.0);
ycbcr470_buffer += bpp_dst;
}
}
Here the babl-extension
---> babl/extensions/ycbcr.c:
#define FIX_1(a) ((double)((a)*256.0*256.0 + 0.5)) #define FIXY_1(a) ((double)((a)*256.0*256.0*219.0/255.0 + 0.5)) #define FIXC_1(a) ((double)((a)*256.0*256.0*224.0/255.0 + 0.5))
static long
rgba_to_ycbcr470 (char *src,
char *dst,
long n)
{
double y, cb, cr;
while (n--)
{
double red = ((double *) src)[0];
double green = ((double *) src)[1];
double blue = ((double *) src)[2];
y = ( FIXY_1(0.2989)*red + FIXY_1(0.5866)*green + FIXY_1(0.1145)*blue +
FIX_1( 16.5))/65536;
cb = (-FIXC_1(0.1688)*red - FIXC_1(0.3312)*green + FIXC_1(0.5000)*blue +
FIX_1(128.5))/65536;
cr = ( FIXC_1(0.5000)*red - FIXC_1(0.4184)*green - FIXC_1(0.0816)*blue +
FIX_1(128.5))/65536;
((double *) dst)[0] = y;
((double *) dst)[1] = cb;
((double *) dst)[2] = cr;
src += 4 * sizeof (double);
dst += 3 * sizeof (double);
}
return n;
}