Add cmyk <-> xyz default colourspace conversion
If no lcms2 library has been found, fallback to default cmyk <-> xyz conversion. Please note that it is an approximative conversion.
This commit is contained in:
parent
5bc342b9b2
commit
d87bf01fdc
@ -39,8 +39,6 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#ifdef HAVE_LCMS2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -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*/
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,7 @@ libcolour_la_SOURCES = \
|
||||
scRGB2XYZ.c \
|
||||
scRGB2BW.c \
|
||||
XYZ2scRGB.c \
|
||||
scRGB2sRGB.c
|
||||
scRGB2sRGB.c
|
||||
|
||||
profiles.c:
|
||||
./wrap_profiles.sh profiles profiles
|
||||
|
@ -39,8 +39,6 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#ifdef HAVE_LCMS2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -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*/
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user