diff --git a/libvips/colour/CMYK2XYZ.c b/libvips/colour/CMYK2XYZ.c index 0feac311..62eaedc4 100644 --- a/libvips/colour/CMYK2XYZ.c +++ b/libvips/colour/CMYK2XYZ.c @@ -39,8 +39,6 @@ #include -#ifdef HAVE_LCMS2 - #include #include @@ -49,6 +47,8 @@ #include "pcolour.h" #include "profiles.h" +#ifdef HAVE_LCMS2 + typedef struct _VipsCMYK2XYZ { VipsOperation parent_instance; @@ -162,22 +162,21 @@ vips_CMYK2XYZ_class_init( VipsCMYK2XYZClass *class ) object_class->nickname = "CMYK2XYZ"; object_class->description = _( "transform CMYK to XYZ" ); - object_class->build = vips_CMYK2XYZ_build; + object_class->build = vips_CMYK2XYZ_build; operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE( class, "in", 1, - _( "Input" ), + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), _( "Input image" ), - VIPS_ARGUMENT_REQUIRED_INPUT, + VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsCMYK2XYZ, in ) ); - VIPS_ARG_IMAGE( class, "out", 100, - _( "Output" ), + VIPS_ARG_IMAGE( class, "out", 100, + _( "Output" ), _( "Output image" ), - VIPS_ARGUMENT_REQUIRED_OUTPUT, + VIPS_ARGUMENT_REQUIRED_OUTPUT, G_STRUCT_OFFSET( VipsCMYK2XYZ, out ) ); - } static void @@ -185,6 +184,72 @@ vips_CMYK2XYZ_init( VipsCMYK2XYZ *CMYK2XYZ ) { } +#else + +typedef VipsColourCode VipsCMYK2XYZ; +typedef VipsColourCodeClass VipsCMYK2XYZClass; + +G_DEFINE_TYPE(VipsCMYK2XYZ, vips_CMYK2XYZ, VIPS_TYPE_COLOUR_CODE); + +void +vips_CMYK2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + unsigned char *p = (unsigned char *) in[0]; + float *q = (float *) out; + + int i; + + for (i = 0; i < width; i++) { + float c = p[0] / 255.0; + float m = p[1] / 255.0; + float y = p[2] / 255.0; + float k = p[3] / 255.0; + + float r = 1.0 - (c * (1.0 - k) + k); + float g = 1.0 - (m * (1.0 - k) + k); + float b = 1.0 - (y * (1.0 - k) + k); + + q[0] = VIPS_D65_X0 * r; + q[1] = VIPS_D65_Y0 * g; + q[2] = VIPS_D65_Z0 * b; + + p += 4; + q += 3; + } +} + +static void +vips_CMYK2XYZ_class_init( VipsCMYK2XYZClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "CMYK2XYZ"; + object_class->description = _( "transform CMYK to XYZ" ); + + colour_class->process_line = vips_CMYK2XYZ_line; +} + +static void +vips_CMYK2XYZ_init( VipsCMYK2XYZ *CMYK2XYZ ) +{ + VipsColour *colour = VIPS_COLOUR( CMYK2XYZ ); + VipsColourCode *code = VIPS_COLOUR_CODE( CMYK2XYZ ); + + colour->interpretation = VIPS_INTERPRETATION_XYZ; + colour->format = VIPS_FORMAT_FLOAT; + colour->bands = 3; + colour->input_bands = 4; + + code->input_coding = VIPS_CODING_NONE; + code->input_format = VIPS_FORMAT_UCHAR; + code->input_interpretation = VIPS_INTERPRETATION_CMYK; +} + #endif /*HAVE_LCMS2*/ /** diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index 09d8b55e..f2b0c83a 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -40,7 +40,7 @@ libcolour_la_SOURCES = \ scRGB2XYZ.c \ scRGB2BW.c \ XYZ2scRGB.c \ - scRGB2sRGB.c + scRGB2sRGB.c profiles.c: ./wrap_profiles.sh profiles profiles diff --git a/libvips/colour/XYZ2CMYK.c b/libvips/colour/XYZ2CMYK.c index e91699e1..7a9e76e6 100644 --- a/libvips/colour/XYZ2CMYK.c +++ b/libvips/colour/XYZ2CMYK.c @@ -39,8 +39,6 @@ #include -#ifdef HAVE_LCMS2 - #include #include @@ -49,6 +47,8 @@ #include "pcolour.h" #include "profiles.h" +#ifdef HAVE_LCMS2 + typedef struct _VipsXYZ2CMYK { VipsOperation parent_instance; @@ -106,22 +106,21 @@ vips_XYZ2CMYK_class_init( VipsXYZ2CMYKClass *class ) object_class->nickname = "XYZ2CMYK"; object_class->description = _( "transform XYZ to CMYK" ); - object_class->build = vips_XYZ2CMYK_build; + object_class->build = vips_XYZ2CMYK_build; operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE( class, "in", 1, - _( "Input" ), + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), _( "Input image" ), - VIPS_ARGUMENT_REQUIRED_INPUT, + VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsXYZ2CMYK, in ) ); - VIPS_ARG_IMAGE( class, "out", 100, - _( "Output" ), + VIPS_ARG_IMAGE( class, "out", 100, + _( "Output" ), _( "Output image" ), - VIPS_ARGUMENT_REQUIRED_OUTPUT, + VIPS_ARGUMENT_REQUIRED_OUTPUT, G_STRUCT_OFFSET( VipsXYZ2CMYK, out ) ); - } static void @@ -129,6 +128,83 @@ vips_XYZ2CMYK_init( VipsXYZ2CMYK *XYZ2CMYK ) { } +#else + +typedef VipsColourCode VipsXYZ2CMYK; +typedef VipsColourCodeClass VipsXYZ2CMYKClass; + +G_DEFINE_TYPE(VipsXYZ2CMYK, vips_XYZ2CMYK, VIPS_TYPE_COLOUR_CODE); + +void +vips_XYZ2CMYK_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + float *p = (float *) in[0]; + unsigned char *q = (unsigned char *) out; + + const float epsilon = 0.00001; + + int i; + + for (i = 0; i < width; i++) { + float c, m, y, k; + float r = p[0] / VIPS_D65_X0; + float g = p[1] / VIPS_D65_Y0; + float b = p[2] / VIPS_D65_Z0; + + if (r < epsilon && g < epsilon && b < epsilon) + q[3] = 255.0; + c = 255.0 - r; + m = 255.0 - g; + y = 255.0 - b; + k = c; + k = VIPS_MIN(k, VIPS_MIN(m, y)); + + c = (c - k) / (255.0 - k) * 255.0; + m = (m - k) / (255.0 - k) * 255.0; + y = (y - k) / (255.0 - k) * 255.0; + + q[0] = (unsigned char) VIPS_CLIP(0, c, 255.0); + q[1] = (unsigned char) VIPS_CLIP(0, m, 255.0); + q[2] = (unsigned char) VIPS_CLIP(0, y, 255.0); + q[3] = (unsigned char) VIPS_CLIP(0, k, 255.0); + + p += 3; + q += 4; + } +} + +static void +vips_XYZ2CMYK_class_init( VipsXYZ2CMYKClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "XYZ2CMYK"; + object_class->description = _( "transform XYZ to CMYK" ); + + colour_class->process_line = vips_XYZ2CMYK_line; +} + +static void +vips_XYZ2CMYK_init( VipsXYZ2CMYK *XYZ2CMYK ) +{ + VipsColour *colour = VIPS_COLOUR( XYZ2CMYK ); + VipsColourCode *code = VIPS_COLOUR_CODE( XYZ2CMYK ); + + colour->interpretation = VIPS_INTERPRETATION_CMYK; + colour->format = VIPS_FORMAT_UCHAR; + colour->bands = 4; + colour->input_bands = 3; + + code->input_coding = VIPS_CODING_NONE; + code->input_format = VIPS_FORMAT_FLOAT; + code->input_interpretation = VIPS_INTERPRETATION_XYZ; +} + #endif /*HAVE_LCMS2*/ /** diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index d8f7ac1c..8e2e8810 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -751,13 +751,13 @@ vips_colour_operation_init( void ) extern GType vips_scRGB2XYZ_get_type( void ); extern GType vips_scRGB2BW_get_type( void ); extern GType vips_XYZ2scRGB_get_type( void ); - extern GType vips_scRGB2sRGB_get_type( void ); + extern GType vips_scRGB2sRGB_get_type( void ); + extern GType vips_CMYK2XYZ_get_type( void ); + extern GType vips_XYZ2CMYK_get_type( void ); #ifdef HAVE_LCMS2 extern GType vips_icc_import_get_type( void ); extern GType vips_icc_export_get_type( void ); extern GType vips_icc_transform_get_type( void ); - extern GType vips_CMYK2XYZ_get_type( void ); - extern GType vips_XYZ2CMYK_get_type( void ); #endif extern GType vips_dE76_get_type( void ); extern GType vips_dE00_get_type( void ); @@ -788,12 +788,12 @@ vips_colour_operation_init( void ) vips_HSV2sRGB_get_type(); vips_XYZ2scRGB_get_type(); vips_scRGB2sRGB_get_type(); + vips_CMYK2XYZ_get_type(); + vips_XYZ2CMYK_get_type(); #ifdef HAVE_LCMS2 vips_icc_import_get_type(); vips_icc_export_get_type(); vips_icc_transform_get_type(); - vips_CMYK2XYZ_get_type(); - vips_XYZ2CMYK_get_type(); #endif vips_dE76_get_type(); vips_dE00_get_type(); diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index d8844c17..2af6bfbf 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -21,6 +21,8 @@ * https://github.com/lovell/sharp/issues/193 * 27/12/18 * - add CMYK conversions + * 09/01/2019 + * - add CMYK <-> XYZ conversions if no lcms2 has been found */ /* @@ -255,8 +257,8 @@ static VipsColourRoute vips_colour_routes[] = { { LABQ, LCH, { vips_LabQ2Lab, vips_Lab2LCh, NULL } }, { LABQ, CMC, { vips_LabQ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } }, { LABQ, LABS, { vips_LabQ2LabS, NULL } }, - { LABQ, CMYK, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2CMYK } }, - { LABQ, scRGB, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2scRGB } }, + { LABQ, CMYK, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2CMYK, NULL } }, + { LABQ, scRGB, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, NULL } }, { LABQ, sRGB, { vips_LabQ2sRGB, NULL } }, { LABQ, HSV, { vips_LabQ2sRGB, vips_sRGB2HSV, NULL } }, { LABQ, BW, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2scRGB,