diff --git a/ChangeLog b/ChangeLog index 20eede70..7d658d70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,7 @@ - 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() as classes + im_LabS2LabQ(), im_LabQ2disp(), im_XYZ2disp(), im_disp2XYZ() as classes 13/9/12 started 7.30.3 - linecache sized itself too large diff --git a/libvips/colour/LCh2Lab.c b/libvips/colour/LCh2Lab.c index 8e3221f3..5743ca0a 100644 --- a/libvips/colour/LCh2Lab.c +++ b/libvips/colour/LCh2Lab.c @@ -96,11 +96,14 @@ vips_LCh2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) void vips_col_Ch2ab( float C, float h, float *a, float *b ) { - float in[3], out[3]; + float in[3]; + float out[3]; + float *x; in[1] = C; in[2] = h; - vips_LCh2Lab_line( NULL, (VipsPel *) out, (VipsPel **) &in, 1 ); + x = in; + vips_LCh2Lab_line( NULL, (VipsPel *) out, (VipsPel **) &x, 1 ); *a = out[1]; *b = out[2]; } diff --git a/libvips/colour/Lab2XYZ.c b/libvips/colour/Lab2XYZ.c index d47fad75..6dd67a80 100644 --- a/libvips/colour/Lab2XYZ.c +++ b/libvips/colour/Lab2XYZ.c @@ -230,17 +230,20 @@ vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... ) void vips_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z ) { - float in[3], out[3]; + float in[3]; + float *x; + float out[3]; VipsLab2XYZ Lab2XYZ; in[0] = L; in[1] = a; in[2] = b; + x = in; Lab2XYZ.X0 = VIPS_D65_X0; Lab2XYZ.Y0 = VIPS_D65_Y0; Lab2XYZ.Z0 = VIPS_D65_Z0; vips_Lab2XYZ_line( (VipsColour *) &Lab2XYZ, - (VipsPel *) out, (VipsPel **) &in, 1 ); + (VipsPel *) out, (VipsPel **) &x, 1 ); *X = out[0]; *Y = out[1]; *Z = out[2]; diff --git a/libvips/colour/LabQ2sRGB.c b/libvips/colour/LabQ2sRGB.c index 4a3339ca..b736c9f1 100644 --- a/libvips/colour/LabQ2sRGB.c +++ b/libvips/colour/LabQ2sRGB.c @@ -47,6 +47,7 @@ #include #include +#include #include "colour.h" @@ -82,6 +83,23 @@ struct im_col_display { float d_P; /* 'Picture' (like contrast) */ }; +/* Structure for holding the lookup tables for XYZ<=>rgb conversion. + * Also holds the luminance to XYZ matrix and the inverse one. + */ +struct im_col_tab_disp { + /*< private >*/ + float t_Yr2r[1501]; /* Conversion of Yr to r */ + float t_Yg2g[1501]; /* Conversion of Yg to g */ + float t_Yb2b[1501]; /* Conversion of Yb to b */ + float t_r2Yr[1501]; /* Conversion of r to Yr */ + float t_g2Yg[1501]; /* Conversion of g to Yg */ + float t_b2Yb[1501]; /* Conversion of b to Yb */ + float mat_XYZ2lum[3][3]; /* XYZ to Yr, Yg, Yb matrix */ + float mat_lum2XYZ[3][3]; /* Yr, Yg, Yb to XYZ matrix */ + float rstep, gstep, bstep; + float ristep, gistep, bistep; +}; + /* Do our own indexing of the arrays below to make sure we get efficient mults. */ #define INDEX( L, A, B ) (L + (A << 6) + (B << 12)) @@ -115,8 +133,9 @@ static VipsPel vips_blue[64 * 64 * 64]; /* Make look_up tables for the Yr,Yb,Yg <=> r,g,b conversions. */ static void * -calcul_tables( struct im_col_tab_disp *table ) +calcul_tables( void *client ) { + struct im_col_tab_disp *table = client; struct im_col_display *d = &srgb_profile; int i, j; @@ -253,10 +272,11 @@ vips_col_sRGB2XYZ( int r, int g, int b, float *X, float *Y, float *Z ) * contain an approximation of the right colour. */ int -vips_col_XYZ2rgb( float X, float Y, float Z, +vips_col_XYZ2sRGB( float X, float Y, float Z, int *r_ret, int *g_ret, int *b_ret, int *or_ret ) { + struct im_col_display *d = &srgb_profile; struct im_col_tab_disp *table = vips_col_make_tables_RGB(); float *mat = &table->mat_XYZ2lum[0][0]; @@ -291,24 +311,15 @@ vips_col_XYZ2rgb( float X, float Y, float Z, * luminosity. */ Yint = (Yr - d->d_Y0R) / table->rstep; - if( Yint > 1500 ) { - or = 1; - Yint = 1500; - } + Yint = VIPS_CLIP( 0, Yint, 1500 ); r = IM_RINT( table->t_Yr2r[Yint] ); Yint = (Yg - d->d_Y0G) / table->gstep; - if( Yint > 1500 ) { - or = 1; - Yint = 1500; - } + Yint = VIPS_CLIP( 0, Yint, 1500 ); g = IM_RINT( table->t_Yg2g[Yint] ); Yint = (Yb - d->d_Y0B) / table->bstep; - if( Yint > 1500 ) { - or = 1; - Yint = 1500; - } + Yint = VIPS_CLIP( 0, Yint, 1500 ); b = IM_RINT( table->t_Yb2b[Yint] ); *r_ret = r; @@ -322,8 +333,8 @@ vips_col_XYZ2rgb( float X, float Y, float Z, /* Build Lab->disp tables. */ -static void -build_tables( void ) +static void * +build_tables( void *client ) { int l, a, b; int t; @@ -341,7 +352,7 @@ build_tables( void ) int oflow; vips_col_Lab2XYZ( L, A, B, &X, &Y, &Z ); - vips_col_XYZ2rgb( X, Y, Z, + vips_col_XYZ2sRGB( X, Y, Z, &rb, &gb, &bb, &oflow ); t = INDEX( l, a, b ); @@ -351,6 +362,8 @@ build_tables( void ) } } } + + return( NULL ); } static void @@ -358,7 +371,7 @@ vips_col_make_tables_LabQ2sRGB( void ) { static GOnce once = G_ONCE_INIT; - (void) g_once( &once, calcul_tables, NULL ); + (void) g_once( &once, build_tables, NULL ); } /* Process a buffer of data. diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index 3ea35fdb..54a26eb2 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -22,12 +22,12 @@ libcolour_la_SOURCES = \ LabS2LabQ.c \ LabQ2LabS.c \ LabQ2sRGB.c \ + XYZ2sRGB.c \ + sRGB2XYZ.c \ im_icc_transform.c \ im_lab_morph.c \ - im_XYZ2disp.c \ im_dE00_fromLab.c \ im_dECMC_fromLab.c \ - im_dE_fromLab.c \ - im_disp2XYZ.c + im_dE_fromLab.c INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ diff --git a/libvips/colour/XYZ2Lab.c b/libvips/colour/XYZ2Lab.c index 51fd266e..1b39d674 100644 --- a/libvips/colour/XYZ2Lab.c +++ b/libvips/colour/XYZ2Lab.c @@ -172,17 +172,20 @@ vips_XYZ2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) void vips_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b ) { - float in[3], out[3]; + float in[3]; + float out[3]; + float *x; VipsXYZ2Lab XYZ2Lab; in[0] = X; in[1] = Y; in[2] = Z; + x = in; XYZ2Lab.X0 = VIPS_D65_X0; XYZ2Lab.Y0 = VIPS_D65_Y0; XYZ2Lab.Z0 = VIPS_D65_Z0; vips_XYZ2Lab_line( (VipsColour *) &XYZ2Lab, - (VipsPel *) out, (VipsPel **) &in, 1 ); + (VipsPel *) out, (VipsPel **) &x, 1 ); *L = out[0]; *a = out[1]; *b = out[2]; diff --git a/libvips/colour/XYZ2sRGB.c b/libvips/colour/XYZ2sRGB.c new file mode 100644 index 00000000..83fcb1e2 --- /dev/null +++ b/libvips/colour/XYZ2sRGB.c @@ -0,0 +1,148 @@ +/* Turn XYZ files into displayable rgb. + * + * Author: J-P. Laurent + * Modified: + * 15/11/94 JC + * - error message added + * - out->Type set to IM_TYPE_RGB + * - memory leak fixed + * 16/11/94 JC + * - uses im_wrapone() + * 15/2/95 JC + * - oops! now uses PEL, not float for output pointer + * 2/1/96 JC + * - sometimes produced incorrect result at extrema + * - reformatted + * - now uses IM_RINT() and clip() + * 18/9/96 JC + * - some speed-ups ... 3x faster + * - slightly less accurate, but who cares + * - added out-of-mem check for table build + * 21/9/12 + * - redone as a class + * - sRGB only, support for other RGBs is now via lcms + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include + +#include + +#include "colour.h" + +typedef VipsColourCode VipsXYZ2sRGB; +typedef VipsColourCodeClass VipsXYZ2sRGBClass; + +G_DEFINE_TYPE( VipsXYZ2sRGB, vips_XYZ2sRGB, VIPS_TYPE_COLOUR_CODE ); + +/* Process a buffer of data. + */ +static void +vips_XYZ2sRGB_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + float *p = (float *) in[0]; + VipsPel *q = (VipsPel *) out; + + int i; + + for( i = 0; i < width; i++ ) { + float X = p[0]; + float Y = p[1]; + float Z = p[2]; + + int r, g, b; + int or; + + vips_col_XYZ2sRGB( X, Y, Z, &r, &g, &b, &or ); + + p += 3; + + q[0] = r; + q[1] = g; + q[2] = b; + + q += 3; + } +} + +static void +vips_XYZ2sRGB_class_init( VipsXYZ2sRGBClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class ); + + object_class->nickname = "XYZ2sRGB"; + object_class->description = _( "convert an XYZ image to sRGB" ); + + colour_class->process_line = vips_XYZ2sRGB_line; + colour_class->coding = VIPS_CODING_NONE; + colour_class->interpretation = VIPS_INTERPRETATION_sRGB; + colour_class->format = VIPS_FORMAT_UCHAR; + colour_class->bands = 3; + + code_class->input_coding = VIPS_CODING_NONE; + code_class->input_bands = 3; + code_class->input_format = VIPS_FORMAT_FLOAT; +} + +static void +vips_XYZ2sRGB_init( VipsXYZ2sRGB *XYZ2sRGB ) +{ +} + +/** + * vips_XYZ2sRGB: + * @in: input image + * @out: output image + * + * Convert an XYZ image to sRGB. + * + * See also: im_LabS2LabQ(), im_XYZ2sRGB(), im_rad2float(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_XYZ2sRGB( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "XYZ2sRGB", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index e4b74844..0e7435a6 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -389,6 +389,9 @@ vips_colour_operation_init( void ) extern GType vips_Lab2LabS_get_type( void ); extern GType vips_rad2float_get_type( void ); extern GType vips_float2rad_get_type( void ); + extern GType vips_LabQ2sRGB_get_type( void ); + extern GType vips_XYZ2sRGB_get_type( void ); + extern GType vips_sRGB2XYZ_get_type( void ); vips_Lab2XYZ_get_type(); vips_XYZ2Lab_get_type(); @@ -406,4 +409,7 @@ vips_colour_operation_init( void ) vips_Lab2LabS_get_type(); vips_rad2float_get_type(); vips_float2rad_get_type(); + vips_LabQ2sRGB_get_type(); + vips_XYZ2sRGB_get_type(); + vips_sRGB2XYZ_get_type(); } diff --git a/libvips/colour/colour_funcs.c b/libvips/colour/colour_funcs.c index fbce34f3..9735a978 100644 --- a/libvips/colour/colour_funcs.c +++ b/libvips/colour/colour_funcs.c @@ -294,20 +294,6 @@ im_col_dE00( float L1, float a1, float b1, /* Quick hack wrappers for common colour functions in the new style. */ -int -vips_LabQ2disp( VipsImage *in, VipsImage **out, - struct im_col_display *disp, ... ) -{ - va_list ap; - int result; - - va_start( ap, disp ); - result = vips_call_split( "im_LabQ2disp", ap, in, out, disp ); - va_end( ap ); - - return( result ); -} - int vips_argb2rgba( VipsImage *in, VipsImage **out, ... ) { @@ -347,21 +333,6 @@ vips_UCS2XYZ( VipsImage *in, VipsImage **out, ... ) return( result ); } -int -vips_XYZ2disp( VipsImage *in, VipsImage **out, - struct im_col_display *disp, ... ) -{ - va_list ap; - int result; - - va_start( ap, disp ); - result = vips_call_split( "im_XYZ2disp", ap, in, out, disp ); - va_end( ap ); - - return( result ); -} - - int im__colour_unary( const char *domain, IMAGE *in, IMAGE *out, VipsType type, diff --git a/libvips/colour/derived.c b/libvips/colour/derived.c index 924594b9..f3af723c 100644 --- a/libvips/colour/derived.c +++ b/libvips/colour/derived.c @@ -158,53 +158,6 @@ im_XYZ2UCS( IMAGE *in, IMAGE *out ) return( 0 ); } -/** - * im_XYZ2sRGB: - * @in: input image - * @out: output image - * - * Convert an image from XYZ to sRGB. The conversion is supposed to be quick - * rather than accurate. Use an ICC profile with im_icc_transform() for more - * precision. - * - * See also: im_icc_transform. - * - * Returns: 0 on success, -1 on error. - */ -int -im_XYZ2sRGB( IMAGE *in, IMAGE *out ) -{ - if( im_XYZ2disp( in, out, im_col_displays( 7 ) ) ) - return( -1 ); - - out->Type = IM_TYPE_sRGB; - - return( 0 ); -} - -/** - * im_sRGB2XYZ: - * @in: input image - * @out: output image - * - * Convert an image from sRGB to XYZ. - * The conversion is supposed to be quick - * rather than accurate. Use an ICC profile with im_icc_transform() for more - * precision. - * - * See also: im_icc_transform. - * - * Returns: 0 on success, -1 on error. - */ -int -im_sRGB2XYZ( IMAGE *in, IMAGE *out ) -{ - if( im_disp2XYZ( in, out, im_col_displays( 7 ) ) ) - return( -1 ); - - return( 0 ); -} - /** * im_dE_fromXYZ: * @in1: first input image diff --git a/libvips/colour/im_XYZ2disp.c b/libvips/colour/im_XYZ2disp.c deleted file mode 100644 index 47cc701e..00000000 --- a/libvips/colour/im_XYZ2disp.c +++ /dev/null @@ -1,155 +0,0 @@ -/* @(#) Turn XYZ files into displayable rgb. - * @(#) - * @(#) Usage: - * @(#) int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) - * @(#) - * @(#) Returns: -1 on error, else 0 - * - * Author: J-P. Laurent - * Modified: - * 15/11/94 JC - * - error message added - * - out->Type set to IM_TYPE_RGB - * - memory leak fixed - * 16/11/94 JC - * - uses im_wrapone() - * 15/2/95 JC - * - oops! now uses PEL, not float for output pointer - * 2/1/96 JC - * - sometimes produced incorrect result at extrema - * - reformatted - * - now uses IM_RINT() and clip() - * 18/9/96 JC - * - some speed-ups ... 3x faster - * - slightly less accurate, but who cares - * - added out-of-mem check for table build - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include -#include - -#include -#include - -/* Process a buffer of data. - */ -void -imb_XYZ2disp( float *p, VipsPel *q, int n, struct im_col_display *d ) -{ - struct im_col_tab_disp *table = im_col_display_get_table( d ); - float rstep = (d->d_YCR - d->d_Y0R) / 1500.0; - float gstep = (d->d_YCG - d->d_Y0G) / 1500.0; - float bstep = (d->d_YCB - d->d_Y0B) / 1500.0; - - int x; - - for( x = 0; x < n; x++ ) { - float Yr, Yg, Yb; - int i; - int r, g, b; - - float X = p[0]; - float Y = p[1]; - float Z = p[2]; - - p += 3; - - /* Multiply through the matrix to get luminosity values. - */ - Yr = table->mat_XYZ2lum[0][0] * X - + table->mat_XYZ2lum[0][1] * Y - + table->mat_XYZ2lum[0][2] * Z; - Yg = table->mat_XYZ2lum[1][0] * X - + table->mat_XYZ2lum[1][1] * Y - + table->mat_XYZ2lum[1][2] * Z; - Yb = table->mat_XYZ2lum[2][0] * X - + table->mat_XYZ2lum[2][1] * Y - + table->mat_XYZ2lum[2][2] * Z; - - /* Clip -ves. - */ - Yr = IM_MAX( Yr, d->d_Y0R ); - Yg = IM_MAX( Yg, d->d_Y0G ); - Yb = IM_MAX( Yb, d->d_Y0B ); - - /* Turn luminosity to colour value. - */ - i = IM_MIN( 1500, (Yr - d->d_Y0R) / rstep ); - r = table->t_Yr2r[i]; - - i = IM_MIN( 1500, (Yg - d->d_Y0G) / gstep ); - g = table->t_Yg2g[i]; - - i = IM_MIN( 1500, (Yb - d->d_Y0B) / bstep ); - b = table->t_Yb2b[i]; - - /* Clip output. - */ - r = IM_MIN( r, d->d_Vrwr ); - g = IM_MIN( g, d->d_Vrwg ); - b = IM_MIN( b, d->d_Vrwb ); - - q[0] = r; - q[1] = g; - q[2] = b; - - q += 3; - } -} - -int -im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) -{ - /* Check input image. - */ - if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT || - in->Coding != IM_CODING_NONE ) { - im_error( "im_XYZ2disp", - "%s", _( "3-band uncoded float only" ) ); - return( -1 ); - } - - if( im_cp_desc( out, in ) ) - return( -1 ); - out->BandFmt = IM_BANDFMT_UCHAR; - out->Type = IM_TYPE_RGB; - - /* Do the processing. - */ - if( im_wrapone( in, out, - (im_wrapone_fn) imb_XYZ2disp, d, NULL ) ) - return( -1 ); - - return( 0 ); -} diff --git a/libvips/colour/im_disp2XYZ.c b/libvips/colour/im_disp2XYZ.c deleted file mode 100644 index bec0608b..00000000 --- a/libvips/colour/im_disp2XYZ.c +++ /dev/null @@ -1,104 +0,0 @@ -/* @(#) Turn displayable rgb files to XYZ. - * @(#) - * @(#) Usage: - * @(#) im_disp2XYZ( imagein, imageout, display ) - * @(#) IMAGE *imagein, *imageout; - * @(#) struct im_col_display *display; - * @(#) - * @(#) uchar in, float out. - * @(#) - * @(#) Returns: -1 on error, else 0 - * Modified: - * 15/11/94 JC - * - memory leak fixed - * - error message added - * 16/11/94 JC - * - partialed - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include -#include - -#include - -/* Convert a buffer. - */ -void -imb_disp2XYZ( VipsPel *p, float *q, int n, struct im_col_display *d ) -{ - int x; - - for( x = 0; x < n; x++ ) { - int r = p[0]; - int g = p[1]; - int b = p[2]; - float X, Y, Z; - p += 3; - - im_col_rgb2XYZ( d, r, g, b, &X, &Y, &Z ); - - q[0] = X; - q[1] = Y; - q[2] = Z; - q += 3; - } -} - -int -im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d ) -{ - /* Check input image. - */ - if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_UCHAR || - in->Coding != IM_CODING_NONE ) { - im_error( "im_disp2XYZ", - "%s", _( "input not 3-band uncoded char" ) ); - return( -1 ); - } - - /* Prepare the output image - */ - if( im_cp_desc( out, in ) ) - return( -1 ); - out->BandFmt = IM_BANDFMT_FLOAT; - out->Type = IM_TYPE_XYZ; - - /* Do the processing. - */ - if( im_wrapone( in, out, - (im_wrapone_fn) imb_disp2XYZ, d, NULL ) ) - return( -1 ); - - return( 0 ); -} diff --git a/libvips/colour/sRGB2XYZ.c b/libvips/colour/sRGB2XYZ.c new file mode 100644 index 00000000..87307768 --- /dev/null +++ b/libvips/colour/sRGB2XYZ.c @@ -0,0 +1,134 @@ +/* Turn displayable rgb files to XYZ. + * + * Modified: + * 15/11/94 JC + * - memory leak fixed + * - error message added + * 16/11/94 JC + * - partialed + * 21/9/12 + * - redone as a class + * - sRGB only, support for other RGBs is now via lcms + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include + +#include + +#include "colour.h" + +typedef VipsColourCode VipssRGB2XYZ; +typedef VipsColourCodeClass VipssRGB2XYZClass; + +G_DEFINE_TYPE( VipssRGB2XYZ, vips_sRGB2XYZ, VIPS_TYPE_COLOUR_CODE ); + +/* Convert a buffer. + */ +static void +vips_sRGB2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + VipsPel *p = in[0]; + float *q = (float *) out; + + int i; + + for( i = 0; i < width; i++ ) { + int r = p[0]; + int g = p[1]; + int b = p[2]; + float X, Y, Z; + + p += 3; + + vips_col_sRGB2XYZ( r, g, b, &X, &Y, &Z ); + + q[0] = X; + q[1] = Y; + q[2] = Z; + + q += 3; + } +} + +static void +vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class ); + + object_class->nickname = "sRGB2XYZ"; + object_class->description = _( "convert an sRGB image to XYZ" ); + + colour_class->process_line = vips_sRGB2XYZ_line; + colour_class->coding = VIPS_CODING_NONE; + colour_class->interpretation = VIPS_INTERPRETATION_XYZ; + colour_class->format = VIPS_FORMAT_FLOAT; + colour_class->bands = 3; + + code_class->input_coding = VIPS_CODING_NONE; + code_class->input_bands = 3; + code_class->input_format = VIPS_FORMAT_UCHAR; +} + +static void +vips_sRGB2XYZ_init( VipssRGB2XYZ *sRGB2XYZ ) +{ +} + +/** + * vips_sRGB2XYZ: + * @in: input image + * @out: output image + * + * Convert an sRGB image to XYZ. + * + * See also: im_LabS2LabQ(), im_sRGB2XYZ(), im_rad2float(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_sRGB2XYZ( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "sRGB2XYZ", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/deprecated/dispatch_types.c b/libvips/deprecated/dispatch_types.c index 9ff4f932..d9863ae5 100644 --- a/libvips/deprecated/dispatch_types.c +++ b/libvips/deprecated/dispatch_types.c @@ -57,28 +57,12 @@ */ #define VEC_SEPS " " -/* Init function for input displays. +/* Init function for input displays. Just a stub nowadays. */ static int input_display_init( im_object *obj, char *str ) { - struct im_col_display *scr = im_col_display_name( str ); - - if( !scr ) { - int i; - - vips_error( "input_display", - _( "unknown display type \"%s\"" ), str ); - vips_error( "input_display", "%s", - _( "display should be one of:\n" ) ); - for( i = 0; (scr = im_col_displays( i )); i++ ) - vips_error( "input_display", - " '%s'\n", scr->d_name ); - - return( -1 ); - } - - *obj = scr; + *obj = NULL; return( 0 ); } @@ -97,7 +81,7 @@ im_type_desc im__input_display = { */ im_type_desc im__output_display = { IM_TYPE_DISPLAY, /* It's a display */ - sizeof( struct im_col_display ),/* Memory to allocate */ + sizeof( void * ), /* Memory to allocate */ IM_TYPE_OUTPUT, /* Output object */ NULL, /* Init function */ NULL /* Destroy function */ @@ -739,62 +723,6 @@ im__dmsprint( im_object obj ) return( 0 ); } -static char *decode_dtype( enum im_col_disp_type type ) -{ - switch( type ) { - case DISP_BARCO: - return( "DISP_BARCO" ); - case DISP_DUMB: - return( "DISP_DUMB" ); - default: - return( "" ); - } -} - -/* Print display stuff. - */ -int -im__displayprint( im_object obj ) -{ - struct im_col_display *scr = (struct im_col_display *) obj; - - printf( "im_col_display:\n" ); - printf( "\td_name: %s\n", scr->d_name ); - printf( "\td_type: %s\n", decode_dtype( scr->d_type ) ); - printf( "\td_mat:\n" ); - printf( "\t\t %g %g %g\n", - scr->d_mat[0][0], scr->d_mat[0][1], scr->d_mat[0][2] ); - printf( "\t\t %g %g %g\n", - scr->d_mat[1][0], scr->d_mat[1][1], scr->d_mat[1][2] ); - printf( "\t\t %g %g %g\n", - scr->d_mat[2][0], scr->d_mat[2][1], scr->d_mat[2][2] ); - - printf( "\td_YCW: %g\n", scr->d_YCW ); - printf( "\td_xCW: %g\n", scr->d_xCW ); - printf( "\td_yCW: %g\n", scr->d_yCW ); - - printf( "\td_YCR: %g\n", scr->d_YCR ); - printf( "\td_YCG: %g\n", scr->d_YCG ); - printf( "\td_YCB: %g\n", scr->d_YCB ); - - printf( "\td_Vrwr: %d\n", scr->d_Vrwr ); - printf( "\td_Vrwg: %d\n", scr->d_Vrwg ); - printf( "\td_Vrwb: %d\n", scr->d_Vrwb ); - - printf( "\td_Y0R: %g\n", scr->d_Y0R ); - printf( "\td_Y0G: %g\n", scr->d_Y0G ); - printf( "\td_Y0B: %g\n", scr->d_Y0B ); - - printf( "\td_gammaR: %g\n", scr->d_gammaR ); - printf( "\td_gammaG: %g\n", scr->d_gammaG ); - printf( "\td_gammaB: %g\n", scr->d_gammaB ); - - printf( "\td_B: %g\n", scr->d_B ); - printf( "\td_P: %g\n", scr->d_P ); - - return( 0 ); -} - /* GValue */ diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 83fdd778..e2f4d8ff 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -2508,3 +2508,51 @@ im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d ) return( 0 ); } + +int +im_sRGB2XYZ( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_sRGB2XYZ( in, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} + +int +im_XYZ2sRGB( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_XYZ2sRGB( in, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} + +int +im_LabQ2sRGB( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_LabQ2sRGB( in, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 79ba8e0e..a76ccf98 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1116,7 +1116,7 @@ vips_foreign_convert_saveable( VipsForeignSave *save ) if( in->Coding == VIPS_CODING_LABQ ) { VipsImage *out; - if( vips_LabQ2disp( in, &out, im_col_displays( 7 ), NULL ) ) { + if( vips_LabQ2sRGB( in, &out, NULL ) ) { g_object_unref( in ); return( -1 ); } @@ -1300,7 +1300,7 @@ vips_foreign_convert_saveable( VipsForeignSave *save ) in->Type == VIPS_INTERPRETATION_LAB ) { VipsImage *out; - if( vips_XYZ2disp( in, &out, im_col_displays( 7 ), NULL ) ) { + if( vips_XYZ2sRGB( in, &out, NULL ) ) { g_object_unref( in ); return( -1 ); } diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 46e92773..84282c2c 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -120,6 +120,8 @@ int vips_XYZ2Lab( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_XYZ2sRGB( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); +int vips_sRGB2XYZ( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); int vips_LCh2UCS( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_UCS2LCh( VipsImage *in, VipsImage **out, ... ) @@ -174,8 +176,6 @@ int im_UCS2XYZ( VipsImage *in, VipsImage *out ); int im_UCS2Lab( VipsImage *in, VipsImage *out ); int im_Lab2UCS( VipsImage *in, VipsImage *out ); int im_XYZ2UCS( VipsImage *in, VipsImage *out ); -int im_sRGB2XYZ( VipsImage *in, VipsImage *out ); -int im_XYZ2sRGB( VipsImage *in, VipsImage *out ); int im_dECMC_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_dE00_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out ); diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index fce5e34f..a513f112 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -109,27 +109,27 @@ typedef enum { /** * VipsInterpretation: - * @VIPS_INTERPREATION_MULTIBAND: generic many-band image - * @VIPS_INTERPREATION_B_W: some kind of single-band image - * @VIPS_INTERPREATION_HISTOGRAM: a 1D image such as a histogram or lookup table - * @VIPS_INTERPREATION_FOURIER: image is in fourier space - * @VIPS_INTERPREATION_XYZ: the first three bands are CIE XYZ - * @VIPS_INTERPREATION_LAB: pixels are in CIE Lab space - * @VIPS_INTERPREATION_CMYK: the first four bands are in CMYK space - * @VIPS_INTERPREATION_LABQ: implies #VIPS_CODING_LABQ - * @VIPS_INTERPREATION_RGB: generic RGB space - * @VIPS_INTERPREATION_UCS: a uniform colourspace based on CMC - * @VIPS_INTERPREATION_LCH: pixels are in CIE LCh space - * @VIPS_INTERPREATION_LABS: CIE LAB coded as three signed 16-bit values - * @VIPS_INTERPREATION_sRGB: pixels are sRGB - * @VIPS_INTERPREATION_YXY: pixels are CIE Yxy - * @VIPS_INTERPREATION_RGB16: generic 16-bit RGB - * @VIPS_INTERPREATION_GREY16: generic 16-bit mono - * @VIPS_INTERPREATION_ARRAY: an array + * @VIPS_INTERPRETATION_MULTIBAND: generic many-band image + * @VIPS_INTERPRETATION_B_W: some kind of single-band image + * @VIPS_INTERPRETATION_HISTOGRAM: a 1D image, eg. histogram or lookup table + * @VIPS_INTERPRETATION_FOURIER: image is in fourier space + * @VIPS_INTERPRETATION_XYZ: the first three bands are CIE XYZ + * @VIPS_INTERPRETATION_LAB: pixels are in CIE Lab space + * @VIPS_INTERPRETATION_CMYK: the first four bands are in CMYK space + * @VIPS_INTERPRETATION_LABQ: implies #VIPS_CODING_LABQ + * @VIPS_INTERPRETATION_RGB: generic RGB space + * @VIPS_INTERPRETATION_UCS: a uniform colourspace based on CMC + * @VIPS_INTERPRETATION_LCH: pixels are in CIE LCh space + * @VIPS_INTERPRETATION_LABS: CIE LAB coded as three signed 16-bit values + * @VIPS_INTERPRETATION_sRGB: pixels are sRGB + * @VIPS_INTERPRETATION_YXY: pixels are CIE Yxy + * @VIPS_INTERPRETATION_RGB16: generic 16-bit RGB + * @VIPS_INTERPRETATION_GREY16: generic 16-bit mono + * @VIPS_INTERPRETATION_ARRAY: an array * * How the values in an image should be interpreted. For example, a - * three-band float image of type #VIPS_INTERPREATION_LAB should have its pixels - * interpreted as coordinates in CIE Lab space. + * three-band float image of type #VIPS_INTERPRETATION_LAB should have its + * pixels interpreted as coordinates in CIE Lab space. * * These values are set by operations as hints to user-interfaces built on top * of VIPS to help them show images to the user in a meaningful way. @@ -143,7 +143,6 @@ typedef enum { VIPS_INTERPRETATION_MULTIBAND = 0, VIPS_INTERPRETATION_B_W = 1, VIPS_INTERPRETATION_HISTOGRAM = 10, - VIPS_INTERPRETATION_FOURIER = 24, VIPS_INTERPRETATION_XYZ = 12, VIPS_INTERPRETATION_LAB = 13, VIPS_INTERPRETATION_CMYK = 15, @@ -154,6 +153,7 @@ typedef enum { VIPS_INTERPRETATION_LABS = 21, VIPS_INTERPRETATION_sRGB = 22, VIPS_INTERPRETATION_YXY = 23, + VIPS_INTERPRETATION_FOURIER = 24, VIPS_INTERPRETATION_RGB16 = 25, VIPS_INTERPRETATION_GREY16 = 26, VIPS_INTERPRETATION_ARRAY = 27 diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 28c7a7b2..4e7c396d 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -730,6 +730,25 @@ int im_Lab2LabS( VipsImage *in, VipsImage *out ); int im_LabS2Lab( VipsImage *in, VipsImage *out ); int im_LabQ2LabS( VipsImage *in, VipsImage *out ); int im_LabS2LabQ( VipsImage *in, VipsImage *out ); +int im_LabQ2sRGB( VipsImage *in, VipsImage *out ); + +int im_XYZ2sRGB( IMAGE *in, IMAGE *out ); +int im_sRGB2XYZ( IMAGE *in, IMAGE *out ); + +struct im_col_display; +#define im_col_displays(S) (NULL) +#define im_LabQ2disp_build_table(A, B) (NULL) +#define im_LabQ2disp_table(A, B, C) (im_LabQ2disp(A, B, C)) + +int im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp ); +int im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *disp ); + +int im_dE_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * ); +int im_dECMC_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * ); + +#define im_disp2XYZ(A, B, C) (im_sRGB2XYZ(A, B)) +#define im_XYZ2disp(A, B, C) (im_XYZ2sRGB(A, B)) +#define im_LabQ2disp(A, B, C) (im_LabQ2sRGB(A, B)) /* ruby-vips uses this */ diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index aa2634d7..f4856ec4 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -423,7 +423,6 @@ vips_interpretation_get_type( void ) {VIPS_INTERPRETATION_MULTIBAND, "VIPS_INTERPRETATION_MULTIBAND", "multiband"}, {VIPS_INTERPRETATION_B_W, "VIPS_INTERPRETATION_B_W", "b-w"}, {VIPS_INTERPRETATION_HISTOGRAM, "VIPS_INTERPRETATION_HISTOGRAM", "histogram"}, - {VIPS_INTERPRETATION_FOURIER, "VIPS_INTERPRETATION_FOURIER", "fourier"}, {VIPS_INTERPRETATION_XYZ, "VIPS_INTERPRETATION_XYZ", "xyz"}, {VIPS_INTERPRETATION_LAB, "VIPS_INTERPRETATION_LAB", "lab"}, {VIPS_INTERPRETATION_CMYK, "VIPS_INTERPRETATION_CMYK", "cmyk"}, @@ -434,6 +433,7 @@ vips_interpretation_get_type( void ) {VIPS_INTERPRETATION_LABS, "VIPS_INTERPRETATION_LABS", "labs"}, {VIPS_INTERPRETATION_sRGB, "VIPS_INTERPRETATION_sRGB", "srgb"}, {VIPS_INTERPRETATION_YXY, "VIPS_INTERPRETATION_YXY", "yxy"}, + {VIPS_INTERPRETATION_FOURIER, "VIPS_INTERPRETATION_FOURIER", "fourier"}, {VIPS_INTERPRETATION_RGB16, "VIPS_INTERPRETATION_RGB16", "rgb16"}, {VIPS_INTERPRETATION_GREY16, "VIPS_INTERPRETATION_GREY16", "grey16"}, {VIPS_INTERPRETATION_ARRAY, "VIPS_INTERPRETATION_ARRAY", "array"}, diff --git a/libvipsCC/VDisplay.cc b/libvipsCC/VDisplay.cc index 1ab30ba0..f2f4d468 100644 --- a/libvipsCC/VDisplay.cc +++ b/libvipsCC/VDisplay.cc @@ -52,28 +52,13 @@ VIPS_NAMESPACE_START static void free_display( im_col_display *d ) { - if( d->d_name ) - im_free( d->d_name ); - im_free( d ); } // Dupe an im_col_display static im_col_display * dup_display( im_col_display *in ) throw( VError ) { - im_col_display *out; - - if( !(out = IM_NEW( NULL, im_col_display )) ) - verror(); - - *out = *in; - if( in->d_name ) - if( !(out->d_name = strdup( in->d_name )) ) { - free_display( out ); - verror( "out of memory" ); - } - - return( out ); + return( in ); } // Remove lut @@ -109,9 +94,6 @@ void VDisplay::refblock::wready() throw( VError ) // Check that luts are up-to-date void VDisplay::refblock::cluts() throw( VError ) { - if( !luts ) - if( !(luts = im_col_make_tables_RGB( NULL, disp )) ) - verror(); } VDisplay::~VDisplay() @@ -140,30 +122,9 @@ VDisplay &VDisplay::operator=( const VDisplay &a ) VDisplay::VDisplay( const char *name ) throw( VError ) { - // Search for a matching name in the VIPS colour list - im_col_display *scr = im_col_display_name( name ); - - if( !scr ) { - VError err; - - err.app( "VDisplay error: " ); - err.app( "unknown display type \"" ).app( name ).app( "\"\n" ); - err.app( "display should be one of:" ); - - for( int i = 0; (scr = im_col_displays( i )); i++ ) { - err.app( " \"" ); - err.app( im_col_displays( i )->d_name ); - err.app( "\"" ); - } - - err.app( "\n" ); - - throw( err ); - } - // Install display ref = new refblock; - ref->disp = scr; + ref->disp = NULL; } VDisplay::VDisplay()