new icc transformer compiles
This commit is contained in:
parent
ecb8faa7cd
commit
e793d38aa7
@ -2,7 +2,8 @@
|
||||
- redone im_Lab2XYZ(), im_XYZ2Lab(), im_Lab2LCh(), im_LCh2Lab(), im_UCS2LCh,
|
||||
im_LCh2UCS(), im_XYZ2Yxy(), im_Yxy2XYZ(), im_float2rad(), im_rad2float(),
|
||||
im_Lab2LabQ(), im_LabQ2Lab(), im_Lab2LabS(), im_LabS2Lab(), im_LabQ2LabS(),
|
||||
im_LabS2LabQ(), im_LabQ2disp(), im_XYZ2disp(), im_disp2XYZ() as classes
|
||||
im_LabS2LabQ(), im_LabQ2disp(), im_XYZ2disp(), im_disp2XYZ(),
|
||||
im_icc_import*(), im_icc_export*(), im_icc_transform*() as classes
|
||||
|
||||
13/9/12 started 7.30.3
|
||||
- linecache sized itself too large
|
||||
|
3
TODO
3
TODO
@ -1,3 +1,6 @@
|
||||
- im_icc_ac2rc needs doing once we have a general 'convert' operator
|
||||
|
||||
|
||||
- boolean.c has
|
||||
|
||||
vips_check_noncomplex( "VipsBoolean", binary->left ) )
|
||||
|
@ -195,9 +195,8 @@ vips_Lab2XYZ_init( VipsLab2XYZ *Lab2XYZ )
|
||||
*
|
||||
* @temp: colour temperature
|
||||
*
|
||||
* Turn Lab to XYZ.
|
||||
*
|
||||
* The colour temperature defaults to D65, but can be specified with @temp.
|
||||
* Turn Lab to XYZ. The colour temperature defaults to D65, but can be
|
||||
* specified with @temp.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
|
@ -24,7 +24,7 @@ libcolour_la_SOURCES = \
|
||||
LabQ2sRGB.c \
|
||||
XYZ2sRGB.c \
|
||||
sRGB2XYZ.c \
|
||||
im_icc_transform.c \
|
||||
icc_transform.c \
|
||||
im_lab_morph.c \
|
||||
im_dE00_fromLab.c \
|
||||
im_dECMC_fromLab.c \
|
||||
|
@ -249,7 +249,12 @@ vips_XYZ2Lab_init( VipsXYZ2Lab *XYZ2Lab )
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
*
|
||||
* Turn XYZ to D65 Lab.
|
||||
* optional arguments:
|
||||
*
|
||||
* @temp: colour temperature
|
||||
*
|
||||
* Turn XYZ to Lab, optionally specifying the colour temperature. @temp
|
||||
* defaults to D65.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
|
@ -83,11 +83,26 @@ vips_colour_gen( VipsRegion *or,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_colour_attach_profile( VipsImage *im, const char *filename )
|
||||
{
|
||||
char *data;
|
||||
unsigned int data_length;
|
||||
|
||||
if( !(data = vips__file_read_name( filename, VIPS_ICC_DIR,
|
||||
&data_length )) )
|
||||
return( -1 );
|
||||
vips_image_set_blob( im, VIPS_META_ICC_NAME,
|
||||
(VipsCallbackFn) g_free, data, data_length );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_colour_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsColour *colour = VIPS_COLOUR( object );
|
||||
VipsColourClass *class = VIPS_COLOUR_GET_CLASS( colour );
|
||||
|
||||
int i;
|
||||
|
||||
@ -104,7 +119,7 @@ vips_colour_build( VipsObject *object )
|
||||
g_object_set( colour, "out", vips_image_new(), NULL );
|
||||
|
||||
if( colour->n > MAX_INPUT_IMAGES ) {
|
||||
vips_error( "VipsColour",
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "too many input images" ) );
|
||||
return( -1 );
|
||||
}
|
||||
@ -116,10 +131,15 @@ vips_colour_build( VipsObject *object )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( colour->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, colour->in );
|
||||
colour->out->Coding = class->coding;
|
||||
colour->out->Type = class->interpretation;
|
||||
colour->out->BandFmt = class->format;
|
||||
colour->out->Bands = class->bands;
|
||||
colour->out->Coding = colour->coding;
|
||||
colour->out->Type = colour->interpretation;
|
||||
colour->out->BandFmt = colour->format;
|
||||
colour->out->Bands = colour->bands;
|
||||
|
||||
if( colour->profile_filename )
|
||||
if( vips_colour_attach_profile( colour->out,
|
||||
colour->profile_filename ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_generate( colour->out,
|
||||
vips_start_many, vips_colour_gen, vips_stop_many,
|
||||
@ -160,6 +180,12 @@ vips_colour_class_init( VipsColourClass *class )
|
||||
static void
|
||||
vips_colour_init( VipsColour *colour )
|
||||
{
|
||||
VipsColourClass *class = VIPS_COLOUR_GET_CLASS( colour );
|
||||
|
||||
colour->coding = class->coding;
|
||||
colour->interpretation = class->interpretation;
|
||||
colour->format = class->format;
|
||||
colour->bands = class->bands;
|
||||
}
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsColourSpace, vips_colour_space, VIPS_TYPE_COLOUR );
|
||||
@ -266,7 +292,6 @@ vips_colour_code_build( VipsObject *object )
|
||||
VipsColour *colour = VIPS_COLOUR( object );
|
||||
VipsColourCode *code = VIPS_COLOUR_CODE( object );
|
||||
VipsColourCodeClass *class = VIPS_COLOUR_CODE_GET_CLASS( object );
|
||||
VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class );
|
||||
|
||||
VipsImage **t;
|
||||
VipsImage *in;
|
||||
@ -279,22 +304,22 @@ vips_colour_code_build( VipsObject *object )
|
||||
|
||||
if( in &&
|
||||
vips_check_coding( VIPS_OBJECT_CLASS( class )->nickname,
|
||||
in, class->input_coding ) )
|
||||
in, code->input_coding ) )
|
||||
return( -1 );
|
||||
|
||||
/* Extra band processing. don't do automatic detach/reattach if either
|
||||
* input or output will be coded.
|
||||
*/
|
||||
if( in &&
|
||||
class->input_coding == VIPS_CODING_NONE &&
|
||||
colour_class->coding == VIPS_CODING_NONE &&
|
||||
class->input_bands > 0 ) {
|
||||
if( in->Bands > class->input_bands ) {
|
||||
code->input_coding == VIPS_CODING_NONE &&
|
||||
colour->coding == VIPS_CODING_NONE &&
|
||||
code->input_bands > 0 ) {
|
||||
if( in->Bands > code->input_bands ) {
|
||||
if( vips_extract_band( in, &t[1], 0,
|
||||
"n", class->input_bands, NULL ) )
|
||||
"n", code->input_bands, NULL ) )
|
||||
return( -1 );
|
||||
if( vips_extract_band( in, &t[2], class->input_bands,
|
||||
"n", in->Bands - class->input_bands,
|
||||
if( vips_extract_band( in, &t[2], code->input_bands,
|
||||
"n", in->Bands - code->input_bands,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[1];
|
||||
@ -302,14 +327,14 @@ vips_colour_code_build( VipsObject *object )
|
||||
}
|
||||
else if( vips_check_bands_atleast(
|
||||
VIPS_OBJECT_CLASS( class )->nickname,
|
||||
in, class->input_bands ) )
|
||||
in, code->input_bands ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( in &&
|
||||
class->input_coding == VIPS_CODING_NONE &&
|
||||
class->input_format != VIPS_FORMAT_NOTSET ) {
|
||||
if( vips_cast( in, &t[3], class->input_format, NULL ) )
|
||||
code->input_coding == VIPS_CODING_NONE &&
|
||||
code->input_format != VIPS_FORMAT_NOTSET ) {
|
||||
if( vips_cast( in, &t[3], code->input_format, NULL ) )
|
||||
return( -1 );
|
||||
in = t[3];
|
||||
}
|
||||
@ -365,6 +390,11 @@ vips_colour_code_class_init( VipsColourCodeClass *class )
|
||||
static void
|
||||
vips_colour_code_init( VipsColourCode *code )
|
||||
{
|
||||
VipsColourCodeClass *class = VIPS_COLOUR_CODE_GET_CLASS( code );
|
||||
|
||||
code->input_coding = class->input_coding;
|
||||
code->input_format = class->input_format;
|
||||
code->input_bands = class->input_bands;
|
||||
}
|
||||
|
||||
/* Called from iofuncs to init all operations in this dir. Use a plugin system
|
||||
@ -392,6 +422,11 @@ vips_colour_operation_init( void )
|
||||
extern GType vips_LabQ2sRGB_get_type( void );
|
||||
extern GType vips_XYZ2sRGB_get_type( void );
|
||||
extern GType vips_sRGB2XYZ_get_type( void );
|
||||
#if defined(HAVE_LCMS) || defined(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 );
|
||||
#endif
|
||||
|
||||
vips_Lab2XYZ_get_type();
|
||||
vips_XYZ2Lab_get_type();
|
||||
@ -412,4 +447,9 @@ vips_colour_operation_init( void )
|
||||
vips_LabQ2sRGB_get_type();
|
||||
vips_XYZ2sRGB_get_type();
|
||||
vips_sRGB2XYZ_get_type();
|
||||
#if defined(HAVE_LCMS) || defined(HAVE_LCMS2)
|
||||
vips_icc_import_get_type();
|
||||
vips_icc_export_get_type();
|
||||
vips_icc_transform_get_type();
|
||||
#endif
|
||||
}
|
||||
|
@ -69,6 +69,17 @@ typedef struct _VipsColour {
|
||||
int n;
|
||||
|
||||
VipsImage *out;
|
||||
|
||||
/* Set fields on ->out from these.
|
||||
*/
|
||||
VipsCoding coding;
|
||||
VipsInterpretation interpretation;
|
||||
VipsBandFormat format;
|
||||
int bands;
|
||||
|
||||
/* Attach this profile, if set.
|
||||
*/
|
||||
char *profile_filename;
|
||||
} VipsColour;
|
||||
|
||||
typedef struct _VipsColourClass {
|
||||
@ -78,12 +89,13 @@ typedef struct _VipsColourClass {
|
||||
*/
|
||||
VipsColourProcessFn process_line;
|
||||
|
||||
/* Set fields on ->out from these.
|
||||
/* Init fields on instance from these.
|
||||
*/
|
||||
VipsCoding coding;
|
||||
VipsInterpretation interpretation;
|
||||
VipsBandFormat format;
|
||||
int bands;
|
||||
|
||||
} VipsColourClass;
|
||||
|
||||
GType vips_colour_get_type( void );
|
||||
@ -143,6 +155,12 @@ typedef struct _VipsColourCode {
|
||||
|
||||
VipsImage *in;
|
||||
|
||||
/* Test in against these, init them from class.
|
||||
*/
|
||||
VipsCoding input_coding;
|
||||
VipsBandFormat input_format;
|
||||
int input_bands;
|
||||
|
||||
} VipsColourCode;
|
||||
|
||||
typedef struct _VipsColourCodeClass {
|
||||
@ -171,4 +189,3 @@ GType vips_colour_code_get_type( void );
|
||||
|
||||
#endif /*VIPS__COLOUR_H*/
|
||||
|
||||
|
||||
|
1014
libvips/colour/icc_transform.c
Normal file
1014
libvips/colour/icc_transform.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2556,3 +2556,84 @@ im_LabQ2sRGB( IMAGE *in, IMAGE *out )
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_icc_transform( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename,
|
||||
const char *output_profile_filename,
|
||||
VipsIntent intent )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_icc_transform( in, &x, output_profile_filename,
|
||||
"input_profile", input_profile_filename,
|
||||
"intent", intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( im_copy( x, out ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_icc_import( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename, VipsIntent intent )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_icc_import( in, &x,
|
||||
"input_profile", input_profile_filename,
|
||||
"intent", intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( im_copy( x, out ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_icc_import_embedded( VipsImage *in, VipsImage *out, VipsIntent intent )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_icc_import( in, &x,
|
||||
"embedded", TRUE,
|
||||
"intent", intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( im_copy( x, out ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_icc_export_depth( VipsImage *in, VipsImage *out, int depth,
|
||||
const char *output_profile_filename, VipsIntent intent )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_icc_export( in, &x, output_profile_filename,
|
||||
"depth", depth,
|
||||
"intent", intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( im_copy( x, out ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ vips_scan_headers = \
|
||||
${top_srcdir}/libvips/include/vips/conversion.h \
|
||||
${top_srcdir}/libvips/include/vips/util.h \
|
||||
${top_srcdir}/libvips/include/vips/image.h \
|
||||
${top_srcdir}/libvips/include/vips/colour.h \
|
||||
${top_srcdir}/libvips/include/vips/operation.h \
|
||||
${top_srcdir}/libvips/include/vips/object.h
|
||||
|
||||
|
@ -92,6 +92,24 @@ extern "C" {
|
||||
#define VIPS_D3250_Y0 (100.0)
|
||||
#define VIPS_D3250_Z0 (45.8501)
|
||||
|
||||
/**
|
||||
* VipsIntent:
|
||||
* @VIPS_INTENT_PERCEPTUAL: perceptual rendering intent
|
||||
* @VIPS_INTENT_RELATIVE: relative colorimetric rendering intent
|
||||
* @VIPS_INTENT_SATURATION: saturation rendering intent
|
||||
* @VIPS_INTENT_ABSOLUTE: absolute colorimetric rendering intent
|
||||
*
|
||||
* The rendering intent. #VIPS_INTENT_ABSOLUTE is best for
|
||||
* scientific work, #VIPS_INTENT_RELATIVE is usually best for
|
||||
* accurate communication with other imaging libraries.
|
||||
*/
|
||||
typedef enum {
|
||||
VIPS_INTENT_PERCEPTUAL = 0,
|
||||
VIPS_INTENT_RELATIVE,
|
||||
VIPS_INTENT_SATURATION,
|
||||
VIPS_INTENT_ABSOLUTE
|
||||
} VipsIntent;
|
||||
|
||||
int vips_LabQ2sRGB( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_rad2float( VipsImage *in, VipsImage **out, ... )
|
||||
@ -135,6 +153,18 @@ int vips_LabS2Lab( VipsImage *in, VipsImage **out, ... )
|
||||
int vips_Lab2LabS( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_icc_present( void );
|
||||
int vips_icc_transform( VipsImage *in, VipsImage **out,
|
||||
const char *output_profile_filename, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_icc_import( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_icc_export( VipsImage *in, VipsImage **out,
|
||||
const char *output_profile, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_icc_ac2rc( VipsImage *in, VipsImage *out,
|
||||
const char *profile_filename );
|
||||
|
||||
void vips_col_Lab2XYZ( float L, float a, float b,
|
||||
float *X, float *Y, float *Z );
|
||||
void vips_col_XYZ2Lab( float X, float Y, float Z,
|
||||
@ -187,27 +217,6 @@ int im_lab_morph( VipsImage *in, VipsImage *out,
|
||||
double L_offset, double L_scale,
|
||||
double a_scale, double b_scale );
|
||||
|
||||
/* Render intents for icc wrappers.
|
||||
*/
|
||||
typedef enum {
|
||||
IM_INTENT_PERCEPTUAL = 0,
|
||||
IM_INTENT_RELATIVE_COLORIMETRIC,
|
||||
IM_INTENT_SATURATION,
|
||||
IM_INTENT_ABSOLUTE_COLORIMETRIC
|
||||
} VipsIntent;
|
||||
|
||||
int im_icc_present( void );
|
||||
int im_icc_transform( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename,
|
||||
const char *output_profile_filename,
|
||||
VipsIntent intent );
|
||||
int im_icc_import( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename, VipsIntent intent );
|
||||
int im_icc_import_embedded( VipsImage *in, VipsImage *out, VipsIntent intent );
|
||||
int im_icc_export_depth( VipsImage *in, VipsImage *out, int depth,
|
||||
const char *output_profile_filename, VipsIntent intent );
|
||||
int im_icc_ac2rc( VipsImage *in, VipsImage *out, const char *profile_filename );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -57,6 +57,9 @@ GType vips_band_format_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_BAND_FORMAT (vips_band_format_get_type())
|
||||
GType vips_coding_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_CODING (vips_coding_get_type())
|
||||
/* enumerations from "../../../libvips/include/vips/colour.h" */
|
||||
GType vips_intent_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_INTENT (vips_intent_get_type())
|
||||
/* enumerations from "../../../libvips/include/vips/operation.h" */
|
||||
GType vips_operation_flags_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_OPERATION_FLAGS (vips_operation_flags_get_type())
|
||||
|
@ -141,6 +141,11 @@ extern "C" {
|
||||
#define IMAGE VipsImage
|
||||
#define REGION VipsRegion
|
||||
|
||||
#define IM_INTENT_PERCEPTUAL VIPS_INTENT_PERCEPTUAL
|
||||
#define IM_INTENT_RELATIVE_COLORIMETRIC VIPS_INTENT_RELATIVE_COLORIMETRIC
|
||||
#define IM_INTENT_SATURATION VIPS_INTENT_SATURATION
|
||||
#define IM_INTENT_ABSOLUTE_COLORIMETRIC VIPS_INTENT_ABSOLUTE_COLORIMETRIC
|
||||
|
||||
/* Renamed macros.
|
||||
*/
|
||||
|
||||
@ -750,6 +755,20 @@ int im_dECMC_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * );
|
||||
#define im_XYZ2disp(A, B, C) (im_XYZ2sRGB(A, B))
|
||||
#define im_LabQ2disp(A, B, C) (im_LabQ2sRGB(A, B))
|
||||
|
||||
int im_icc_transform( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename,
|
||||
const char *output_profile_filename,
|
||||
VipsIntent intent );
|
||||
|
||||
#define im_icc_present vips_icc_present
|
||||
|
||||
int im_icc_import( VipsImage *in, VipsImage *out,
|
||||
const char *input_profile_filename, VipsIntent intent );
|
||||
int im_icc_import_embedded( VipsImage *in, VipsImage *out, VipsIntent intent );
|
||||
int im_icc_export_depth( VipsImage *in, VipsImage *out, int depth,
|
||||
const char *output_profile_filename, VipsIntent intent );
|
||||
int im_icc_ac2rc( VipsImage *in, VipsImage *out, const char *profile_filename );
|
||||
|
||||
/* ruby-vips uses this
|
||||
*/
|
||||
#define vips_class_map_concrete_all vips_class_map_all
|
||||
|
@ -47,6 +47,7 @@ vips_scan_headers = \
|
||||
${top_srcdir}/libvips/include/vips/util.h \
|
||||
${top_srcdir}/libvips/include/vips/image.h \
|
||||
${top_srcdir}/libvips/include/vips/operation.h \
|
||||
${top_srcdir}/libvips/include/vips/colour.h \
|
||||
${top_srcdir}/libvips/include/vips/object.h
|
||||
|
||||
enumtypes.c: $(vips_scan_headers) Makefile
|
||||
|
@ -511,6 +511,26 @@ vips_operation_flags_get_type( void )
|
||||
|
||||
return( etype );
|
||||
}
|
||||
/* enumerations from "../../libvips/include/vips/colour.h" */
|
||||
GType
|
||||
vips_intent_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GEnumValue values[] = {
|
||||
{VIPS_INTENT_PERCEPTUAL, "VIPS_INTENT_PERCEPTUAL", "perceptual"},
|
||||
{VIPS_INTENT_RELATIVE, "VIPS_INTENT_RELATIVE", "relative"},
|
||||
{VIPS_INTENT_SATURATION, "VIPS_INTENT_SATURATION", "saturation"},
|
||||
{VIPS_INTENT_ABSOLUTE, "VIPS_INTENT_ABSOLUTE", "absolute"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_enum_register_static( "VipsIntent", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
/* enumerations from "../../libvips/include/vips/object.h" */
|
||||
GType
|
||||
vips_argument_flags_get_type( void )
|
||||
|
Loading…
Reference in New Issue
Block a user