From 1bddb78f6aa0996a514f0419c26e199714d62aa0 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 11 Dec 2012 13:50:58 +0000 Subject: [PATCH 1/4] split sRGB <-> XYZ up split sRGB <-> XYZ into sRGB <-> scRGB <-> XYZ so we can support scRGB as a colourspace --- libvips/colour/LabQ2sRGB.c | 142 ++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/libvips/colour/LabQ2sRGB.c b/libvips/colour/LabQ2sRGB.c index 06d9a6a1..a39f176e 100644 --- a/libvips/colour/LabQ2sRGB.c +++ b/libvips/colour/LabQ2sRGB.c @@ -18,6 +18,10 @@ * - faster and more accurate sRGB <-> XYZ conversion * 6/11/12 * - added a 16-bit path + * 11/12/12 + * - spot NaN, Inf in XYZ2RGB, they break LUT indexing + * - split sRGB <-> XYZ into sRGB <-> scRGB <-> XYZ so we can support + * scRGB as a colourspace */ /* @@ -84,30 +88,6 @@ static int vips_Y2v_16[65536 + 1]; */ static float vips_v2Y_16[65536]; -/* We need Y in 0 - 100. We can save three muls later if we pre-scale the - * matrix. - * - * The matrix already includes the D65 channel weighting, so we just scale by - * Y. - */ -#define SCALE (VIPS_D65_Y0) - -/* linear RGB -> XYZ matrix. - */ -static float vips_mat_RGB2XYZ[3][3] = { - { SCALE * 0.4124, SCALE * 0.3576, SCALE * 0.18056 }, - { SCALE * 0.2126, SCALE * 0.7152, SCALE * 0.0722 }, - { SCALE * 0.0193, SCALE * 0.1192, SCALE * 0.9505 } -}; - -/* XYZ -> linear RGB matrix. - */ -static float vips_mat_XYZ2RGB[3][3] = { - { 3.2406 / SCALE, -1.5372 / SCALE, -0.4986 / SCALE }, - { -0.9689 / SCALE, 1.8758 / SCALE, 0.0415 / SCALE }, - { 0.0557 / SCALE, -0.2040 / SCALE, 1.0570 / SCALE } -}; - /* 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)) @@ -176,33 +156,45 @@ vips_col_make_tables_RGB_8( void ) } } -/* RGB to XYZ. +/* sRGB to scRGB. * - * @range is eg. 256 for 8-bit data, + * @range is eg. 256 for 8-bit data. */ static int -vips_col_sRGB2XYZ( int range, float *lut, - int r, int g, int b, float *X, float *Y, float *Z ) +vips_col_sRGB2scRGB( int range, float *lut, + int r, int g, int b, float *R, float *G, float *B ) { int maxval = range - 1; - float Yr, Yg, Yb; int i; i = VIPS_CLIP( 0, r, maxval ); - Yr = lut[i]; + *R = lut[i]; i = VIPS_CLIP( 0, g, maxval ); - Yg = lut[i]; + *G = lut[i]; i = VIPS_CLIP( 0, b, maxval ); - Yb = lut[i]; + *B = lut[i]; - *X = vips_mat_RGB2XYZ[0][0] * Yr + - vips_mat_RGB2XYZ[0][1] * Yg + vips_mat_RGB2XYZ[0][2] * Yb; - *Y = vips_mat_RGB2XYZ[1][0] * Yr + - vips_mat_RGB2XYZ[1][1] * Yg + vips_mat_RGB2XYZ[1][2] * Yb; - *Z = vips_mat_RGB2XYZ[2][0] * Yr + - vips_mat_RGB2XYZ[2][1] * Yg + vips_mat_RGB2XYZ[2][2] * Yb; + return( 0 ); +} + +/* We need Y in 0 - 100. We can save three muls later if we pre-scale the + * matrix. + * + * The matrix already includes the D65 channel weighting, so we just scale by + * Y. + */ +#define SCALE (VIPS_D65_Y0) + +/* scRGB to XYZ. + */ +static int +vips_col_scRGB2XYZ( float R, float G, float B, float *X, float *Y, float *Z ) +{ + *X = SCALE * 0.4124 * R + SCALE * 0.3576 * G + SCALE * 0.18056 * B; + *Y = SCALE * 0.2126 * R + SCALE * 0.7152 * G + SCALE * 0.07220 * B; + *Z = SCALE * 0.0193 * R + SCALE * 0.1192 * G + SCALE * 0.9505 * B; return( 0 ); } @@ -210,9 +202,12 @@ vips_col_sRGB2XYZ( int range, float *lut, int vips_col_sRGB2XYZ_8( int r, int g, int b, float *X, float *Y, float *Z ) { + float R, G, B; + vips_col_make_tables_RGB_8(); - return( vips_col_sRGB2XYZ( 256, vips_v2Y_8, r, g, b, X, Y, Z ) ); + return( vips_col_sRGB2scRGB( 256, vips_v2Y_8, r, g, b, &R, &G, &B ) || + vips_col_scRGB2XYZ( R, G, B, X, Y, Z ) ); } static void * @@ -242,23 +237,40 @@ vips_col_make_tables_RGB_16( void ) int vips_col_sRGB2XYZ_16( int r, int g, int b, float *X, float *Y, float *Z ) { + float R, G, B; + vips_col_make_tables_RGB_16(); - return( vips_col_sRGB2XYZ( 65536, vips_v2Y_16, r, g, b, X, Y, Z ) ); + return( vips_col_sRGB2scRGB( 65536, vips_v2Y_16, + r, g, b, &R, &G, &B ) || + vips_col_scRGB2XYZ( R, G, B, X, Y, Z ) ); } -/* Turn XYZ into display colour. Return or=1 for out of gamut - rgb will - * contain an approximation of the right colour. +/* Turn XYZ into scRGB. */ static int -vips_col_XYZ2sRGB( int range, int *lut, - float X, float Y, float Z, +vips_col_XYZ2scRGB( float X, float Y, float Z, float *R, float *G, float *B ) +{ + *R = 3.2406 / SCALE * X + -1.5372 / SCALE * Y + -0.4986 / SCALE * Z; + *G = -0.9689 / SCALE * X + 1.8758 / SCALE * Y + 0.0415 / SCALE * Z; + *B = 0.0557 / SCALE * X + -0.2040 / SCALE * Y + 1.0570 / SCALE * Z; + + return( 0 ); +} + +/* Turn scRGB into sRGB. Return or=1 for out of gamut - rgb will contain an + * approximation of the right colour. + * + * Return -1 for NaN, Inf etc. + */ +static int +vips_col_scRGB2sRGB( int range, int *lut, + float R, float G, float B, int *r, int *g, int *b, int *or_ret ) { int maxval = range - 1; - float Yr, Yg, Yb; int or; float Yf; int Yi; @@ -267,9 +279,9 @@ vips_col_XYZ2sRGB( int range, int *lut, /* XYZ can be Nan, Inf etc. Throw those values out, they will break * our clipping. */ - if( !isnormal( X ) || - !isnormal( Y ) || - !isnormal( Z ) ) { + if( !isnormal( R ) || + !isnormal( G ) || + !isnormal( B ) ) { *r = 0; *g = 0; *b = 0; @@ -277,15 +289,6 @@ vips_col_XYZ2sRGB( int range, int *lut, return( -1 ); } - /* Multiply through the matrix to get luminosity values. - */ - Yr = vips_mat_XYZ2RGB[0][0] * X + - vips_mat_XYZ2RGB[0][1] * Y + vips_mat_XYZ2RGB[0][2] * Z; - Yg = vips_mat_XYZ2RGB[1][0] * X + - vips_mat_XYZ2RGB[1][1] * Y + vips_mat_XYZ2RGB[1][2] * Z; - Yb = vips_mat_XYZ2RGB[2][0] * X + - vips_mat_XYZ2RGB[2][1] * Y + vips_mat_XYZ2RGB[2][2] * Z; - /* Clip range, set the out-of-range flag. */ #define CLIP( L, V, H ) { \ @@ -307,20 +310,20 @@ vips_col_XYZ2sRGB( int range, int *lut, or = 0; - Yf = Yr * maxval; - CLIP( 0, Yf, maxval); + Yf = R * maxval; + CLIP( 0, Yf, maxval ); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); *r = VIPS_RINT( v ); - Yf = Yg * maxval; - CLIP( 0, Yf, maxval); + Yf = G * maxval; + CLIP( 0, Yf, maxval ); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); *g = VIPS_RINT( v ); - Yf = Yb * maxval; - CLIP( 0, Yf, maxval); + Yf = B * maxval; + CLIP( 0, Yf, maxval ); Yi = (int) Yf; v = lut[Yi] + (lut[Yi + 1] - lut[Yi]) * (Yf - Yi); *b = VIPS_RINT( v ); @@ -336,9 +339,13 @@ vips_col_XYZ2sRGB_8( float X, float Y, float Z, int *r, int *g, int *b, int *or ) { + float R, G, B; + vips_col_make_tables_RGB_8(); - return( vips_col_XYZ2sRGB( 256, vips_Y2v_8, X, Y, Z, r, g, b, or ) ); + return( vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ) || + vips_col_scRGB2sRGB( 256, vips_Y2v_8, + R, G, B, r, g, b, or ) ); } int @@ -346,10 +353,13 @@ vips_col_XYZ2sRGB_16( float X, float Y, float Z, int *r, int *g, int *b, int *or ) { + float R, G, B; + vips_col_make_tables_RGB_16(); - return( vips_col_XYZ2sRGB( 65536, vips_Y2v_16, - X, Y, Z, r, g, b, or ) ); + return( vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ) || + vips_col_scRGB2sRGB( 65536, vips_Y2v_16, + R, G, B, r, g, b, or ) ); } /* Build Lab->disp dither tables. From c341f0d134114b7e10d218ef8659772862332f3c Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 11 Dec 2012 15:25:28 +0000 Subject: [PATCH 2/4] add scRGB functions --- ChangeLog | 1 + TODO | 7 ++ libvips/colour/LabQ2sRGB.c | 121 ++++++++---------- libvips/colour/Makefile.am | 6 +- libvips/colour/XYZ2sRGB.c | 8 +- libvips/colour/XYZ2scRGB.c | 118 ++++++++++++++++++ libvips/colour/colour.c | 8 ++ libvips/colour/sRGB2XYZ.c | 12 +- libvips/colour/sRGB2scRGB.c | 186 ++++++++++++++++++++++++++++ libvips/colour/scRGB2XYZ.c | 123 +++++++++++++++++++ libvips/colour/scRGB2sRGB.c | 222 ++++++++++++++++++++++++++++++++++ libvips/include/vips/colour.h | 30 ++++- libvips/include/vips/image.h | 4 +- libvips/iofuncs/enumtypes.c | 1 + libvips/iofuncs/image.c | 2 +- 15 files changed, 767 insertions(+), 82 deletions(-) create mode 100644 libvips/colour/XYZ2scRGB.c create mode 100644 libvips/colour/sRGB2scRGB.c create mode 100644 libvips/colour/scRGB2XYZ.c create mode 100644 libvips/colour/scRGB2sRGB.c diff --git a/ChangeLog b/ChangeLog index cbd0d639..64a3b0fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,7 @@ - add binary complex operations, with cross_phase as the only one so far - added vips_bandbool(), with vips_bandand(), _bandor(), _bandeor() as convenience functions +- added scRGB colourspace, linear light float space with sRGB primaries 14/11/12 started 7.30.6 - capture tiff warnings earlier diff --git a/TODO b/TODO index 62c0b7e6..1df9b486 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ +- get rid of RGB, RGB16, just have sRGB and scRGB? maybe get rid of GREY16 + too? + +- get rid of sRGB2XYZ? is using two ops much slower? + +- add colourconvert paths for scRGB + - now we've removed round-to-nearest from NN, we need something extra in the affine transform to displace the input cods diff --git a/libvips/colour/LabQ2sRGB.c b/libvips/colour/LabQ2sRGB.c index a39f176e..3094cfc3 100644 --- a/libvips/colour/LabQ2sRGB.c +++ b/libvips/colour/LabQ2sRGB.c @@ -98,6 +98,29 @@ static VipsPel vips_red[64 * 64 * 64]; static VipsPel vips_green[64 * 64 * 64]; static VipsPel vips_blue[64 * 64 * 64]; +/* sRGB to scRGB. + * + * @range is eg. 256 for 8-bit data. + */ +static int +vips_col_sRGB2scRGB( int range, float *lut, + int r, int g, int b, float *R, float *G, float *B ) +{ + int maxval = range - 1; + int i; + + i = VIPS_CLIP( 0, r, maxval ); + *R = lut[i]; + + i = VIPS_CLIP( 0, g, maxval ); + *G = lut[i]; + + i = VIPS_CLIP( 0, b, maxval ); + *B = lut[i]; + + return( 0 ); +} + /* Create the sRGB linear and unlinear luts. @range is eg. 256 for 8-bit luts. */ static void @@ -156,58 +179,12 @@ vips_col_make_tables_RGB_8( void ) } } -/* sRGB to scRGB. - * - * @range is eg. 256 for 8-bit data. - */ -static int -vips_col_sRGB2scRGB( int range, float *lut, - int r, int g, int b, float *R, float *G, float *B ) -{ - int maxval = range - 1; - int i; - - i = VIPS_CLIP( 0, r, maxval ); - *R = lut[i]; - - i = VIPS_CLIP( 0, g, maxval ); - *G = lut[i]; - - i = VIPS_CLIP( 0, b, maxval ); - *B = lut[i]; - - return( 0 ); -} - -/* We need Y in 0 - 100. We can save three muls later if we pre-scale the - * matrix. - * - * The matrix already includes the D65 channel weighting, so we just scale by - * Y. - */ -#define SCALE (VIPS_D65_Y0) - -/* scRGB to XYZ. - */ -static int -vips_col_scRGB2XYZ( float R, float G, float B, float *X, float *Y, float *Z ) -{ - *X = SCALE * 0.4124 * R + SCALE * 0.3576 * G + SCALE * 0.18056 * B; - *Y = SCALE * 0.2126 * R + SCALE * 0.7152 * G + SCALE * 0.07220 * B; - *Z = SCALE * 0.0193 * R + SCALE * 0.1192 * G + SCALE * 0.9505 * B; - - return( 0 ); -} - int -vips_col_sRGB2XYZ_8( int r, int g, int b, float *X, float *Y, float *Z ) +vips_col_sRGB2scRGB_8( int r, int g, int b, float *R, float *G, float *B ) { - float R, G, B; - vips_col_make_tables_RGB_8(); - return( vips_col_sRGB2scRGB( 256, vips_v2Y_8, r, g, b, &R, &G, &B ) || - vips_col_scRGB2XYZ( R, G, B, X, Y, Z ) ); + return( vips_col_sRGB2scRGB( 256, vips_v2Y_8, r, g, b, R, G, B ) ); } static void * @@ -235,20 +212,33 @@ vips_col_make_tables_RGB_16( void ) } int -vips_col_sRGB2XYZ_16( int r, int g, int b, float *X, float *Y, float *Z ) +vips_col_sRGB2scRGB_16( int r, int g, int b, float *R, float *G, float *B ) { - float R, G, B; - vips_col_make_tables_RGB_16(); - return( vips_col_sRGB2scRGB( 65536, vips_v2Y_16, - r, g, b, &R, &G, &B ) || - vips_col_scRGB2XYZ( R, G, B, X, Y, Z ) ); + return( vips_col_sRGB2scRGB( 65536, vips_v2Y_16, r, g, b, R, G, B ) ); +} + +/* The matrix already includes the D65 channel weighting, so we just scale by + * Y. + */ +#define SCALE (VIPS_D65_Y0) + +/* scRGB to XYZ. + */ +int +vips_col_scRGB2XYZ( float R, float G, float B, float *X, float *Y, float *Z ) +{ + *X = SCALE * 0.4124 * R + SCALE * 0.3576 * G + SCALE * 0.18056 * B; + *Y = SCALE * 0.2126 * R + SCALE * 0.7152 * G + SCALE * 0.07220 * B; + *Z = SCALE * 0.0193 * R + SCALE * 0.1192 * G + SCALE * 0.9505 * B; + + return( 0 ); } /* Turn XYZ into scRGB. */ -static int +int vips_col_XYZ2scRGB( float X, float Y, float Z, float *R, float *G, float *B ) { *R = 3.2406 / SCALE * X + -1.5372 / SCALE * Y + -0.4986 / SCALE * Z; @@ -335,31 +325,24 @@ vips_col_scRGB2sRGB( int range, int *lut, } int -vips_col_XYZ2sRGB_8( float X, float Y, float Z, +vips_col_scRGB2sRGB_8( float R, float G, float B, int *r, int *g, int *b, int *or ) { - float R, G, B; - vips_col_make_tables_RGB_8(); - return( vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ) || - vips_col_scRGB2sRGB( 256, vips_Y2v_8, - R, G, B, r, g, b, or ) ); + return( vips_col_scRGB2sRGB( 256, vips_Y2v_8, R, G, B, r, g, b, or ) ); } int -vips_col_XYZ2sRGB_16( float X, float Y, float Z, +vips_col_scRGB2sRGB_16( float R, float G, float B, int *r, int *g, int *b, int *or ) { - float R, G, B; - vips_col_make_tables_RGB_16(); - return( vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ) || - vips_col_scRGB2sRGB( 65536, vips_Y2v_16, - R, G, B, r, g, b, or ) ); + return( vips_col_scRGB2sRGB( 65536, vips_Y2v_16, + R, G, B, r, g, b, or ) ); } /* Build Lab->disp dither tables. @@ -379,11 +362,13 @@ build_tables( void *client ) float A = (signed char) (a << 2); float B = (signed char) (b << 2); float X, Y, Z; + float Rf, Gf, Bf; int rb, gb, bb; int oflow; vips_col_Lab2XYZ( L, A, B, &X, &Y, &Z ); - vips_col_XYZ2sRGB_8( X, Y, Z, + vips_col_XYZ2scRGB( X, Y, Z, &Rf, &Gf, &Bf ); + vips_col_scRGB2sRGB_8( Rf, Gf, Bf, &rb, &gb, &bb, &oflow ); t = INDEX( l, a, b ); diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index 53141c97..c0f6f1cb 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -26,6 +26,10 @@ libcolour_la_SOURCES = \ LabQ2LabS.c \ LabQ2sRGB.c \ XYZ2sRGB.c \ - sRGB2XYZ.c + sRGB2XYZ.c \ + sRGB2scRGB.c \ + scRGB2XYZ.c \ + XYZ2scRGB.c \ + scRGB2sRGB.c INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ diff --git a/libvips/colour/XYZ2sRGB.c b/libvips/colour/XYZ2sRGB.c index 6cdebb54..cd3932ad 100644 --- a/libvips/colour/XYZ2sRGB.c +++ b/libvips/colour/XYZ2sRGB.c @@ -85,10 +85,12 @@ vips_XYZ2sRGB_line_8( VipsPel *q, float *p, int width ) float Y = p[1]; float Z = p[2]; + float R, G, B; int r, g, b; int or; - vips_col_XYZ2sRGB_8( X, Y, Z, &r, &g, &b, &or ); + vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ); + vips_col_scRGB2sRGB_8( R, G, B, &r, &g, &b, &or ); p += 3; @@ -110,10 +112,12 @@ vips_XYZ2sRGB_line_16( unsigned short *q, float *p, int width ) float Y = p[1]; float Z = p[2]; + float R, G, B; int r, g, b; int or; - vips_col_XYZ2sRGB_16( X, Y, Z, &r, &g, &b, &or ); + vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ); + vips_col_scRGB2sRGB_16( R, G, B, &r, &g, &b, &or ); p += 3; diff --git a/libvips/colour/XYZ2scRGB.c b/libvips/colour/XYZ2scRGB.c new file mode 100644 index 00000000..6a5e527f --- /dev/null +++ b/libvips/colour/XYZ2scRGB.c @@ -0,0 +1,118 @@ +/* Turn XYZ to scRGB colourspace. + * + * 11/12/12 + * - from Yxy2XYZ.c + */ + +/* + + 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 VipsColourSpace VipsXYZ2scRGB; +typedef VipsColourSpaceClass VipsXYZ2scRGBClass; + +G_DEFINE_TYPE( VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_COLOUR_SPACE ); + +void +vips_XYZ2scRGB_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + float *p = (float *) in[0]; + float *q = (float *) out; + + int i; + + for( i = 0; i < width; i++ ) { + float X = p[0]; + float Y = p[1]; + float Z = p[2]; + + float R, G, B; + + p += 3; + + vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ); + + q[0] = R; + q[1] = G; + q[2] = B; + + q += 3; + } +} + +static void +vips_XYZ2scRGB_class_init( VipsXYZ2scRGBClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + + object_class->nickname = "XYZ2scRGB"; + object_class->description = _( "transform XYZ to scRGB" ); + + colour_class->process_line = vips_XYZ2scRGB_line; +} + +static void +vips_XYZ2scRGB_init( VipsXYZ2scRGB *XYZ2scRGB ) +{ + VipsColour *colour = VIPS_COLOUR( XYZ2scRGB ); + + colour->interpretation = VIPS_INTERPRETATION_scRGB; +} + +/** + * vips_XYZ2scRGB: + * @in: input image + * @out: output image + * + * Turn XYZ to Yxy. + * + * Returns: 0 on success, -1 on error + */ +int +vips_XYZ2scRGB( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "XYZ2scRGB", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index a324b21c..df27988e 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -798,6 +798,10 @@ 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 ); + extern GType vips_sRGB2scRGB_get_type( void ); + extern GType vips_scRGB2XYZ_get_type( void ); + extern GType vips_XYZ2scRGB_get_type( void ); + extern GType vips_scRGB2sRGB_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 ); @@ -827,6 +831,10 @@ vips_colour_operation_init( void ) vips_LabQ2sRGB_get_type(); vips_XYZ2sRGB_get_type(); vips_sRGB2XYZ_get_type(); + vips_sRGB2scRGB_get_type(); + vips_scRGB2XYZ_get_type(); + vips_XYZ2scRGB_get_type(); + vips_scRGB2sRGB_get_type(); #if defined(HAVE_LCMS) || defined(HAVE_LCMS2) vips_icc_import_get_type(); vips_icc_export_get_type(); diff --git a/libvips/colour/sRGB2XYZ.c b/libvips/colour/sRGB2XYZ.c index 0579a1ad..e52ed5eb 100644 --- a/libvips/colour/sRGB2XYZ.c +++ b/libvips/colour/sRGB2XYZ.c @@ -10,7 +10,7 @@ * - redone as a class * - sRGB only, support for other RGBs is now via lcms * 6/11/12 - * - add 15-bit sRGB import + * - add 16-bit sRGB import */ /* @@ -67,11 +67,14 @@ vips_sRGB2XYZ_line_8( float *q, VipsPel *p, int width ) int r = p[0]; int g = p[1]; int b = p[2]; + + float R, G, B; float X, Y, Z; p += 3; - vips_col_sRGB2XYZ_8( r, g, b, &X, &Y, &Z ); + vips_col_sRGB2scRGB_8( r, g, b, &R, &G, &B ); + vips_col_scRGB2XYZ( R, G, B, &X, &Y, &Z ); q[0] = X; q[1] = Y; @@ -92,11 +95,14 @@ vips_sRGB2XYZ_line_16( float *q, unsigned short *p, int width ) int r = p[0]; int g = p[1]; int b = p[2]; + + float R, G, B; float X, Y, Z; p += 3; - vips_col_sRGB2XYZ_16( r, g, b, &X, &Y, &Z ); + vips_col_sRGB2scRGB_16( r, g, b, &R, &G, &B ); + vips_col_scRGB2XYZ( R, G, B, &X, &Y, &Z ); q[0] = X; q[1] = Y; diff --git a/libvips/colour/sRGB2scRGB.c b/libvips/colour/sRGB2scRGB.c new file mode 100644 index 00000000..cbd33475 --- /dev/null +++ b/libvips/colour/sRGB2scRGB.c @@ -0,0 +1,186 @@ +/* Turn displayable rgb files to scRGB. + * + * 11/12/12 + * - from sRGB2XYZ.c + */ + +/* + + 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 VipssRGB2scRGB; +typedef VipsColourCodeClass VipssRGB2scRGBClass; + +G_DEFINE_TYPE( VipssRGB2scRGB, vips_sRGB2scRGB, VIPS_TYPE_COLOUR_CODE ); + +/* Convert a buffer of 8-bit pixels. + */ +static void +vips_sRGB2scRGB_line_8( float *q, VipsPel *p, int width ) +{ + int i; + + for( i = 0; i < width; i++ ) { + int r = p[0]; + int g = p[1]; + int b = p[2]; + + float R, G, B; + + p += 3; + + vips_col_sRGB2scRGB_8( r, g, b, &R, &G, &B ); + + q[0] = R; + q[1] = G; + q[2] = B; + + q += 3; + } +} + +/* Convert a buffer of 16-bit pixels. + */ +static void +vips_sRGB2scRGB_line_16( float *q, unsigned short *p, int width ) +{ + int i; + + for( i = 0; i < width; i++ ) { + int r = p[0]; + int g = p[1]; + int b = p[2]; + + float R, G, B; + + p += 3; + + vips_col_sRGB2scRGB_16( r, g, b, &R, &G, &B ); + + q[0] = R; + q[1] = G; + q[2] = B; + + q += 3; + } +} + +static void +vips_sRGB2scRGB_line( VipsColour *colour, + VipsPel *out, VipsPel **in, int width ) +{ + if( colour->in[0]->BandFmt == VIPS_FORMAT_UCHAR ) + vips_sRGB2scRGB_line_8( (float *) out, + (VipsPel *) in[0], width ); + else + vips_sRGB2scRGB_line_16( (float *) out, + (unsigned short *) in[0], width ); +} + +static int +vips_sRGB2scRGB_build( VipsObject *object ) +{ + VipsColourCode *code = (VipsColourCode *) object; + + if( code->in ) + code->input_format = + code->in->BandFmt == VIPS_FORMAT_USHORT ? + VIPS_FORMAT_USHORT : VIPS_FORMAT_UCHAR; + + if( VIPS_OBJECT_CLASS( vips_sRGB2scRGB_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_sRGB2scRGB_class_init( VipssRGB2scRGBClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + + object_class->nickname = "sRGB2scRGB"; + object_class->description = _( "convert an sRGB image to scRGB" ); + object_class->build = vips_sRGB2scRGB_build; + + colour_class->process_line = vips_sRGB2scRGB_line; +} + +static void +vips_sRGB2scRGB_init( VipssRGB2scRGB *sRGB2scRGB ) +{ + VipsColour *colour = VIPS_COLOUR( sRGB2scRGB ); + VipsColourCode *code = VIPS_COLOUR_CODE( sRGB2scRGB ); + + colour->coding = VIPS_CODING_NONE; + colour->interpretation = VIPS_INTERPRETATION_scRGB; + colour->format = VIPS_FORMAT_FLOAT; + colour->bands = 3; + + code->input_coding = VIPS_CODING_NONE; + code->input_bands = 3; + + /* The default. This can get changed above ^^ if we see a + * 16-bit input. + */ + code->input_format = VIPS_FORMAT_UCHAR; +} + +/** + * vips_sRGB2scRGB: + * @in: input image + * @out: output image + * + * Convert an sRGB image to scRGB. + * + * See also: vips_sRGB2XYZ(), vips_rad2float(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_sRGB2scRGB( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "sRGB2scRGB", ap, in, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/colour/scRGB2XYZ.c b/libvips/colour/scRGB2XYZ.c new file mode 100644 index 00000000..b5c0b273 --- /dev/null +++ b/libvips/colour/scRGB2XYZ.c @@ -0,0 +1,123 @@ +/* Turn scRGB to XYZ colourspace. + * + * Modified: + * 29/5/02 JC + * - from lab2xyz + * 2/11/09 + * - gtkdoc + * - cleanups + * 20/9/12 + * redo as a class + */ + +/* + + 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 VipsColourSpace VipsscRGB2XYZ; +typedef VipsColourSpaceClass VipsscRGB2XYZClass; + +G_DEFINE_TYPE( VipsscRGB2XYZ, vips_scRGB2XYZ, VIPS_TYPE_COLOUR_SPACE ); + +void +vips_scRGB2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) +{ + float *p = (float *) in[0]; + float *q = (float *) out; + + int i; + + for( i = 0; i < width; i++ ) { + float R = p[0]; + float G = p[1]; + float B = p[2]; + + float X, Y, Z; + + p += 3; + + vips_col_scRGB2XYZ( R, G, B, &X, &Y, &Z ); + + q[0] = X; + q[1] = Y; + q[2] = Z; + q += 3; + } +} + +static void +vips_scRGB2XYZ_class_init( VipsscRGB2XYZClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + + object_class->nickname = "scRGB2XYZ"; + object_class->description = _( "transform scRGB to XYZ" ); + + colour_class->process_line = vips_scRGB2XYZ_line; +} + +static void +vips_scRGB2XYZ_init( VipsscRGB2XYZ *scRGB2XYZ ) +{ + VipsColour *colour = VIPS_COLOUR( scRGB2XYZ ); + + colour->interpretation = VIPS_INTERPRETATION_XYZ; +} + +/** + * vips_scRGB2XYZ: + * @in: input image + * @out: output image + * + * Turn XYZ to scRGB. + * + * Returns: 0 on success, -1 on error + */ +int +vips_scRGB2XYZ( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "scRGB2XYZ", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/colour/scRGB2sRGB.c b/libvips/colour/scRGB2sRGB.c new file mode 100644 index 00000000..21857246 --- /dev/null +++ b/libvips/colour/scRGB2sRGB.c @@ -0,0 +1,222 @@ +/* Turn scRGB files into displayable rgb. + * + * 11/12/12 + * - from XYZ2sRGB.c + */ + +/* + + 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 struct _VipsscRGB2sRGB { + VipsColourCode parent_instance; + + int depth; +} VipsscRGB2sRGB; + +typedef VipsColourCodeClass VipsscRGB2sRGBClass; + +G_DEFINE_TYPE( VipsscRGB2sRGB, vips_scRGB2sRGB, VIPS_TYPE_COLOUR_CODE ); + +/* Process a buffer of data. + */ +static void +vips_scRGB2sRGB_line_8( VipsPel *q, float *p, int width ) +{ + int i; + + for( i = 0; i < width; i++ ) { + float R = p[0]; + float G = p[1]; + float B = p[2]; + + int r, g, b; + int or; + + vips_col_scRGB2sRGB_8( R, G, B, &r, &g, &b, &or ); + + p += 3; + + q[0] = r; + q[1] = g; + q[2] = b; + + q += 3; + } +} + +static void +vips_scRGB2sRGB_line_16( unsigned short *q, float *p, int width ) +{ + int i; + + for( i = 0; i < width; i++ ) { + float R = p[0]; + float G = p[1]; + float B = p[2]; + + int r, g, b; + int or; + + vips_col_scRGB2sRGB_16( R, G, B, &r, &g, &b, &or ); + + p += 3; + + q[0] = r; + q[1] = g; + q[2] = b; + + q += 3; + } +} + +static void +vips_scRGB2sRGB_line( VipsColour *colour, + VipsPel *out, VipsPel **in, int width ) +{ + VipsscRGB2sRGB *scRGB2sRGB = (VipsscRGB2sRGB *) colour; + + if( scRGB2sRGB->depth == 16 ) + vips_scRGB2sRGB_line_16( (unsigned short *) out, + (float *) in[0], width ); + else + vips_scRGB2sRGB_line_8( (VipsPel *) out, + (float *) in[0], width ); +} + +static int +vips_scRGB2sRGB_build( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsscRGB2sRGB *scRGB2sRGB = (VipsscRGB2sRGB *) object; + VipsColour *colour = VIPS_COLOUR( scRGB2sRGB ); + + switch( scRGB2sRGB->depth ) { + case 16: + colour->interpretation = VIPS_INTERPRETATION_RGB16; + colour->format = VIPS_FORMAT_USHORT; + break; + + case 8: + colour->interpretation = VIPS_INTERPRETATION_sRGB; + colour->format = VIPS_FORMAT_UCHAR; + break; + + default: + vips_error( class->nickname, + "%s", _( "depth must be 8 or 16" ) ); + return( -1 ); + } + + if( VIPS_OBJECT_CLASS( vips_scRGB2sRGB_parent_class )->build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_scRGB2sRGB_class_init( VipsscRGB2sRGBClass *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 = "scRGB2sRGB"; + object_class->description = _( "convert an scRGB image to sRGB" ); + object_class->build = vips_scRGB2sRGB_build; + + colour_class->process_line = vips_scRGB2sRGB_line; + + VIPS_ARG_INT( class, "depth", 130, + _( "Depth" ), + _( "Output device space depth in bits" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsscRGB2sRGB, depth ), + 8, 16, 8 ); +} + +static void +vips_scRGB2sRGB_init( VipsscRGB2sRGB *scRGB2sRGB ) +{ + VipsColour *colour = VIPS_COLOUR( scRGB2sRGB ); + VipsColourCode *code = VIPS_COLOUR_CODE( scRGB2sRGB ); + + /* Just the default, can be overridden, see above. + */ + colour->coding = VIPS_CODING_NONE; + colour->interpretation = VIPS_INTERPRETATION_sRGB; + colour->format = VIPS_FORMAT_UCHAR; + colour->bands = 3; + + code->input_coding = VIPS_CODING_NONE; + code->input_bands = 3; + code->input_format = VIPS_FORMAT_FLOAT; + + scRGB2sRGB->depth = 8; +} + +/** + * vips_scRGB2sRGB: + * @in: input image + * @out: output image + * + * Optional arguments: + * + * @depth: depth of output image in bits + * + * Convert an scRGB image to sRGB. Set @depth to 16 to get 16-bit output. + * + * See also: im_LabS2LabQ(), im_scRGB2sRGB(), im_rad2float(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_scRGB2sRGB( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "scRGB2sRGB", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 1a3d896c..8cefcc20 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -141,10 +141,21 @@ int vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_XYZ2Lab( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); + +int vips_XYZ2scRGB( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); +int vips_scRGB2sRGB( 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_sRGB2scRGB( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); +int vips_scRGB2XYZ( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); + int vips_LCh2CMC( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_CMC2LCh( VipsImage *in, VipsImage **out, ... ) @@ -193,13 +204,20 @@ float vips_col_Lcmc2L( float Lcmc ); float vips_col_Ccmc2C( float Ccmc ); float vips_col_Chcmc2h( float C, float hcmc ); -int vips_col_XYZ2sRGB_8( float X, float Y, float Z, - int *r, int *g, int *b, int *or_ret ); -int vips_col_sRGB2XYZ_8( int r, int g, int b, float *X, float *Y, float *Z ); +int vips_col_sRGB2scRGB_8( int r, int g, int b, float *R, float *G, float *B ); +int vips_col_sRGB2scRGB_16( int r, int g, int b, float *R, float *G, float *B ); -int vips_col_XYZ2sRGB_16( float X, float Y, float Z, - int *r, int *g, int *b, int *or_ret ); -int vips_col_sRGB2XYZ_16( int r, int g, int b, float *X, float *Y, float *Z ); +int vips_col_scRGB2XYZ( float R, float G, float B, + float *X, float *Y, float *Z ); +int vips_col_XYZ2scRGB( float X, float Y, float Z, + float *R, float *G, float *B ); + +int vips_col_scRGB2sRGB_8( float R, float G, float B, + int *r, int *g, int *b, + int *or_ret ); +int vips_col_scRGB2sRGB_16( float R, float G, float B, + int *r, int *g, int *b, + int *or_ret ); float vips_pythagoras( float L1, float a1, float b1, float L2, float a2, float b2 ); diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 087d3996..0b3478df 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -122,6 +122,7 @@ typedef enum { * @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_scRGB: pixels are scRGB * @VIPS_INTERPRETATION_YXY: pixels are CIE Yxy * @VIPS_INTERPRETATION_RGB16: generic 16-bit RGB * @VIPS_INTERPRETATION_GREY16: generic 16-bit mono @@ -156,7 +157,8 @@ typedef enum { VIPS_INTERPRETATION_FOURIER = 24, VIPS_INTERPRETATION_RGB16 = 25, VIPS_INTERPRETATION_GREY16 = 26, - VIPS_INTERPRETATION_ARRAY = 27 + VIPS_INTERPRETATION_ARRAY = 27, + VIPS_INTERPRETATION_scRGB = 28 } VipsInterpretation; /** diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index 1b5a7e38..d961c0d4 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -493,6 +493,7 @@ vips_interpretation_get_type( void ) {VIPS_INTERPRETATION_RGB16, "VIPS_INTERPRETATION_RGB16", "rgb16"}, {VIPS_INTERPRETATION_GREY16, "VIPS_INTERPRETATION_GREY16", "grey16"}, {VIPS_INTERPRETATION_ARRAY, "VIPS_INTERPRETATION_ARRAY", "array"}, + {VIPS_INTERPRETATION_scRGB, "VIPS_INTERPRETATION_scRGB", "scrgb"}, {0, NULL, NULL} }; diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 017f1d6e..ed35c890 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -457,7 +457,7 @@ vips_image_sanity( VipsObject *object, VipsBuf *buf ) image->Coding != VIPS_CODING_NONE && image->Coding != VIPS_CODING_LABQ && image->Coding != VIPS_CODING_RAD) || - image->Type > VIPS_INTERPRETATION_ARRAY || + image->Type > VIPS_INTERPRETATION_scRGB || image->dtype > VIPS_IMAGE_PARTIAL || image->dhint > VIPS_DEMAND_STYLE_ANY ) vips_buf_appends( buf, "bad enum\n" ); From 89ff89ebf88976c2327086b307b96d1a2564db92 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 12 Dec 2012 12:43:26 +0000 Subject: [PATCH 3/4] remove sRGB2XYZ and back now go via scRGB --- TODO | 7 - libvips/colour/Makefile.am | 2 - libvips/colour/XYZ2sRGB.c | 245 ------------------------------- libvips/colour/colour.c | 2 - libvips/colour/colourspace.c | 78 +++++++--- libvips/colour/sRGB2XYZ.c | 200 ------------------------- libvips/colour/sRGB2scRGB.c | 13 +- libvips/colour/scRGB2sRGB.c | 25 +++- libvips/deprecated/vips7compat.c | 26 ++-- libvips/include/vips/colour.h | 5 - 10 files changed, 101 insertions(+), 502 deletions(-) delete mode 100644 libvips/colour/XYZ2sRGB.c delete mode 100644 libvips/colour/sRGB2XYZ.c diff --git a/TODO b/TODO index 1df9b486..62c0b7e6 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,3 @@ -- get rid of RGB, RGB16, just have sRGB and scRGB? maybe get rid of GREY16 - too? - -- get rid of sRGB2XYZ? is using two ops much slower? - -- add colourconvert paths for scRGB - - now we've removed round-to-nearest from NN, we need something extra in the affine transform to displace the input cods diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index c0f6f1cb..d7808610 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -25,8 +25,6 @@ libcolour_la_SOURCES = \ LabS2LabQ.c \ LabQ2LabS.c \ LabQ2sRGB.c \ - XYZ2sRGB.c \ - sRGB2XYZ.c \ sRGB2scRGB.c \ scRGB2XYZ.c \ XYZ2scRGB.c \ diff --git a/libvips/colour/XYZ2sRGB.c b/libvips/colour/XYZ2sRGB.c deleted file mode 100644 index cd3932ad..00000000 --- a/libvips/colour/XYZ2sRGB.c +++ /dev/null @@ -1,245 +0,0 @@ -/* 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 - * 6/11/12 - * - added 16-bit option - */ - -/* - - 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 struct _VipsXYZ2sRGB { - VipsColourCode parent_instance; - - int depth; -} VipsXYZ2sRGB; - -typedef VipsColourCodeClass VipsXYZ2sRGBClass; - -G_DEFINE_TYPE( VipsXYZ2sRGB, vips_XYZ2sRGB, VIPS_TYPE_COLOUR_CODE ); - -/* Process a buffer of data. - */ -static void -vips_XYZ2sRGB_line_8( VipsPel *q, float *p, int width ) -{ - int i; - - for( i = 0; i < width; i++ ) { - float X = p[0]; - float Y = p[1]; - float Z = p[2]; - - float R, G, B; - int r, g, b; - int or; - - vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ); - vips_col_scRGB2sRGB_8( R, G, B, &r, &g, &b, &or ); - - p += 3; - - q[0] = r; - q[1] = g; - q[2] = b; - - q += 3; - } -} - -static void -vips_XYZ2sRGB_line_16( unsigned short *q, float *p, int width ) -{ - int i; - - for( i = 0; i < width; i++ ) { - float X = p[0]; - float Y = p[1]; - float Z = p[2]; - - float R, G, B; - int r, g, b; - int or; - - vips_col_XYZ2scRGB( X, Y, Z, &R, &G, &B ); - vips_col_scRGB2sRGB_16( R, G, B, &r, &g, &b, &or ); - - p += 3; - - q[0] = r; - q[1] = g; - q[2] = b; - - q += 3; - } -} - -static void -vips_XYZ2sRGB_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) -{ - VipsXYZ2sRGB *XYZ2sRGB = (VipsXYZ2sRGB *) colour; - - if( XYZ2sRGB->depth == 16 ) - vips_XYZ2sRGB_line_16( (unsigned short *) out, (float *) in[0], - width ); - else - vips_XYZ2sRGB_line_8( (VipsPel *) out, (float *) in[0], width ); -} - -static int -vips_XYZ2sRGB_build( VipsObject *object ) -{ - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); - VipsXYZ2sRGB *XYZ2sRGB = (VipsXYZ2sRGB *) object; - VipsColour *colour = VIPS_COLOUR( XYZ2sRGB ); - - switch( XYZ2sRGB->depth ) { - case 16: - colour->interpretation = VIPS_INTERPRETATION_RGB16; - colour->format = VIPS_FORMAT_USHORT; - break; - - case 8: - colour->interpretation = VIPS_INTERPRETATION_sRGB; - colour->format = VIPS_FORMAT_UCHAR; - break; - - default: - vips_error( class->nickname, - "%s", _( "depth must be 8 or 16" ) ); - return( -1 ); - } - - if( VIPS_OBJECT_CLASS( vips_XYZ2sRGB_parent_class )->build( object ) ) - return( -1 ); - - return( 0 ); -} - -static void -vips_XYZ2sRGB_class_init( VipsXYZ2sRGBClass *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 = "XYZ2sRGB"; - object_class->description = _( "convert an XYZ image to sRGB" ); - object_class->build = vips_XYZ2sRGB_build; - - colour_class->process_line = vips_XYZ2sRGB_line; - - VIPS_ARG_INT( class, "depth", 130, - _( "Depth" ), - _( "Output device space depth in bits" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsXYZ2sRGB, depth ), - 8, 16, 8 ); -} - -static void -vips_XYZ2sRGB_init( VipsXYZ2sRGB *XYZ2sRGB ) -{ - VipsColour *colour = VIPS_COLOUR( XYZ2sRGB ); - VipsColourCode *code = VIPS_COLOUR_CODE( XYZ2sRGB ); - - /* Just the default, can be overridden, see above. - */ - colour->coding = VIPS_CODING_NONE; - colour->interpretation = VIPS_INTERPRETATION_sRGB; - colour->format = VIPS_FORMAT_UCHAR; - colour->bands = 3; - - code->input_coding = VIPS_CODING_NONE; - code->input_bands = 3; - code->input_format = VIPS_FORMAT_FLOAT; - - XYZ2sRGB->depth = 8; -} - -/** - * vips_XYZ2sRGB: - * @in: input image - * @out: output image - * - * Optional arguments: - * - * @depth: depth of output image in bits - * - * Convert an XYZ image to sRGB. Set @depth to 16 to get 16-bit output. - * - * 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 df27988e..5a491c41 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -829,8 +829,6 @@ vips_colour_operation_init( void ) vips_rad2float_get_type(); vips_float2rad_get_type(); vips_LabQ2sRGB_get_type(); - vips_XYZ2sRGB_get_type(); - vips_sRGB2XYZ_get_type(); vips_sRGB2scRGB_get_type(); vips_scRGB2XYZ_get_type(); vips_XYZ2scRGB_get_type(); diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index fb940a82..0eb7afd5 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -49,9 +49,9 @@ #include "colour.h" static int -vips_XYZ2RGB16( VipsImage *in, VipsImage **out, ... ) +vips_scRGB2RGB16( VipsImage *in, VipsImage **out, ... ) { - return( vips_XYZ2sRGB( in, out, "depth", 16, NULL ) ); + return( vips_scRGB2sRGB( in, out, "depth", 16, NULL ) ); } /* A colour-transforming function. @@ -82,6 +82,7 @@ typedef struct _VipsColourRoute { #define LCH VIPS_INTERPRETATION_LCH #define CMC VIPS_INTERPRETATION_CMC #define LABS VIPS_INTERPRETATION_LABS +#define scRGB VIPS_INTERPRETATION_scRGB #define sRGB VIPS_INTERPRETATION_sRGB #define RGB16 VIPS_INTERPRETATION_RGB16 #define YXY VIPS_INTERPRETATION_YXY @@ -94,8 +95,9 @@ static VipsColourRoute vips_colour_routes[] = { { XYZ, LCH, { vips_XYZ2Lab, vips_Lab2LCh, NULL } }, { XYZ, CMC, { vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } }, { XYZ, LABS, { vips_XYZ2Lab, vips_Lab2LabS, NULL } }, - { XYZ, sRGB, { vips_XYZ2sRGB, NULL } }, - { XYZ, RGB16, { vips_XYZ2RGB16, NULL } }, + { XYZ, scRGB, { vips_XYZ2scRGB, NULL } }, + { XYZ, sRGB, { vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } }, + { XYZ, RGB16, { vips_XYZ2scRGB, vips_scRGB2RGB16, NULL } }, { XYZ, YXY, { vips_XYZ2Yxy, NULL } }, { LAB, XYZ, { vips_Lab2XYZ, NULL } }, @@ -103,8 +105,10 @@ static VipsColourRoute vips_colour_routes[] = { { LAB, LCH, { vips_Lab2LCh, NULL } }, { LAB, CMC, { vips_Lab2LCh, vips_LCh2CMC, NULL } }, { LAB, LABS, { vips_Lab2LabS, NULL } }, - { LAB, sRGB, { vips_Lab2XYZ, vips_XYZ2sRGB, NULL } }, - { LAB, RGB16, { vips_Lab2XYZ, vips_XYZ2RGB16, NULL } }, + { LAB, scRGB, { vips_Lab2XYZ, vips_XYZ2scRGB, NULL } }, + { LAB, sRGB, { vips_Lab2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } }, + { LAB, RGB16, { vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2RGB16, NULL } }, { LAB, YXY, { vips_Lab2XYZ, vips_XYZ2Yxy, NULL } }, { LABQ, XYZ, { vips_LabQ2Lab, vips_Lab2XYZ, NULL } }, @@ -112,8 +116,10 @@ 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, scRGB, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2scRGB } }, { LABQ, sRGB, { vips_LabQ2sRGB, NULL } }, - { LABQ, RGB16, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2RGB16, NULL } }, + { LABQ, RGB16, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2RGB16, NULL } }, { LABQ, YXY, { vips_LabQ2Lab, vips_Lab2XYZ, vips_XYZ2Yxy, NULL } }, { LCH, XYZ, { vips_LCh2Lab, vips_Lab2XYZ, NULL } }, @@ -121,8 +127,11 @@ static VipsColourRoute vips_colour_routes[] = { { LCH, LABQ, { vips_LCh2Lab, vips_Lab2LabQ, NULL } }, { LCH, CMC, { vips_LCh2CMC, NULL } }, { LCH, LABS, { vips_LCh2Lab, vips_Lab2LabS, NULL } }, - { LCH, sRGB, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2sRGB, NULL } }, - { LCH, RGB16, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2RGB16, NULL } }, + { LCH, scRGB, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, NULL } }, + { LCH, sRGB, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2sRGB, NULL } }, + { LCH, RGB16, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2RGB16, NULL } }, { LCH, YXY, { vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2Yxy, NULL } }, { CMC, XYZ, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, NULL } }, @@ -130,10 +139,12 @@ static VipsColourRoute vips_colour_routes[] = { { CMC, LABQ, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2LabQ, NULL } }, { CMC, LCH, { vips_CMC2LCh, NULL } }, { CMC, LABS, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2LabS, NULL } }, + { CMC, scRGB, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, + vips_XYZ2scRGB, NULL } }, { CMC, sRGB, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, - vips_XYZ2sRGB, NULL } }, + vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } }, { CMC, RGB16, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, - vips_XYZ2RGB16, NULL } }, + vips_XYZ2scRGB, vips_scRGB2RGB16, NULL } }, { CMC, YXY, { vips_CMC2LCh, vips_LCh2Lab, vips_Lab2XYZ, vips_XYZ2Yxy, NULL } }, @@ -142,19 +153,37 @@ static VipsColourRoute vips_colour_routes[] = { { LABS, LABQ, { vips_LabS2LabQ, NULL } }, { LABS, LCH, { vips_LabS2Lab, vips_Lab2LCh, NULL } }, { LABS, CMC, { vips_LabS2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } }, - { LABS, sRGB, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2sRGB, NULL } }, - { LABS, RGB16, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2RGB16, NULL } }, + { LABS, scRGB, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, NULL } }, + { LABS, sRGB, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2sRGB, NULL } }, + { LABS, RGB16, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2scRGB, + vips_scRGB2RGB16, NULL } }, { LABS, YXY, { vips_LabS2Lab, vips_Lab2XYZ, vips_XYZ2Yxy, NULL } }, - { sRGB, XYZ, { vips_sRGB2XYZ, NULL } }, - { sRGB, LAB, { vips_sRGB2XYZ, vips_XYZ2Lab, NULL } }, - { sRGB, LABQ, { vips_sRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } }, - { sRGB, LCH, { vips_sRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } }, - { sRGB, CMC, { vips_sRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, - vips_LCh2CMC, NULL } }, - { sRGB, LABS, { vips_sRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } }, - { sRGB, RGB16, { vips_sRGB2XYZ, vips_XYZ2RGB16, NULL } }, - { sRGB, YXY, { vips_sRGB2XYZ, vips_XYZ2Yxy, NULL } }, + { scRGB, XYZ, { vips_scRGB2XYZ, NULL } }, + { scRGB, LAB, { vips_scRGB2XYZ, vips_XYZ2Lab, NULL } }, + { scRGB, LABQ, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabQ, NULL } }, + { scRGB, LCH, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LCh, NULL } }, + { scRGB, CMC, { vips_scRGB2XYZ, vips_XYZ2Lab, + vips_Lab2LCh, vips_LCh2CMC, NULL } }, + { scRGB, sRGB, { vips_scRGB2sRGB, NULL } }, + { scRGB, LABS, { vips_scRGB2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } }, + { scRGB, RGB16, { vips_scRGB2RGB16, NULL } }, + { scRGB, YXY, { vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } }, + + { sRGB, XYZ, { vips_sRGB2scRGB, vips_scRGB2XYZ, NULL } }, + { sRGB, LAB, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, NULL } }, + { sRGB, LABQ, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, + vips_Lab2LabQ, NULL } }, + { sRGB, LCH, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, + vips_Lab2LCh, NULL } }, + { sRGB, CMC, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, + vips_Lab2LCh, vips_LCh2CMC, NULL } }, + { sRGB, scRGB, { vips_sRGB2scRGB, NULL } }, + { sRGB, LABS, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Lab, + vips_Lab2LabS, NULL } }, + { sRGB, RGB16, { vips_sRGB2scRGB, vips_scRGB2RGB16, NULL } }, + { sRGB, YXY, { vips_sRGB2scRGB, vips_scRGB2XYZ, vips_XYZ2Yxy, NULL } }, { YXY, XYZ, { vips_Yxy2XYZ, NULL } }, { YXY, LAB, { vips_Yxy2XYZ, vips_XYZ2Lab, NULL } }, @@ -163,8 +192,9 @@ static VipsColourRoute vips_colour_routes[] = { { YXY, CMC, { vips_Yxy2XYZ, vips_XYZ2Lab, vips_Lab2LCh, vips_LCh2CMC, NULL } }, { YXY, LABS, { vips_Yxy2XYZ, vips_XYZ2Lab, vips_Lab2LabS, NULL } }, - { YXY, sRGB, { vips_Yxy2XYZ, vips_XYZ2sRGB, NULL } }, - { YXY, RGB16, { vips_Yxy2XYZ, vips_XYZ2RGB16, NULL } }, + { YXY, scRGB, { vips_Yxy2XYZ, vips_XYZ2scRGB, NULL } }, + { YXY, sRGB, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2sRGB, NULL } }, + { YXY, RGB16, { vips_Yxy2XYZ, vips_XYZ2scRGB, vips_scRGB2RGB16, NULL } }, }; /* Is an image in a supported colourspace. diff --git a/libvips/colour/sRGB2XYZ.c b/libvips/colour/sRGB2XYZ.c deleted file mode 100644 index e52ed5eb..00000000 --- a/libvips/colour/sRGB2XYZ.c +++ /dev/null @@ -1,200 +0,0 @@ -/* 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 - * 6/11/12 - * - add 16-bit sRGB import - */ - -/* - - 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 of 8-bit pixels. - */ -static void -vips_sRGB2XYZ_line_8( float *q, VipsPel *p, int width ) -{ - int i; - - for( i = 0; i < width; i++ ) { - int r = p[0]; - int g = p[1]; - int b = p[2]; - - float R, G, B; - float X, Y, Z; - - p += 3; - - vips_col_sRGB2scRGB_8( r, g, b, &R, &G, &B ); - vips_col_scRGB2XYZ( R, G, B, &X, &Y, &Z ); - - q[0] = X; - q[1] = Y; - q[2] = Z; - - q += 3; - } -} - -/* Convert a buffer of 16-bit pixels. - */ -static void -vips_sRGB2XYZ_line_16( float *q, unsigned short *p, int width ) -{ - int i; - - for( i = 0; i < width; i++ ) { - int r = p[0]; - int g = p[1]; - int b = p[2]; - - float R, G, B; - float X, Y, Z; - - p += 3; - - vips_col_sRGB2scRGB_16( r, g, b, &R, &G, &B ); - vips_col_scRGB2XYZ( R, G, B, &X, &Y, &Z ); - - q[0] = X; - q[1] = Y; - q[2] = Z; - - q += 3; - } -} - -static void -vips_sRGB2XYZ_line( VipsColour *colour, - VipsPel *out, VipsPel **in, int width ) -{ - if( colour->in[0]->BandFmt == VIPS_FORMAT_UCHAR ) - vips_sRGB2XYZ_line_8( (float *) out, - (VipsPel *) in[0], width ); - else - vips_sRGB2XYZ_line_16( (float *) out, - (unsigned short *) in[0], width ); -} - -static int -vips_sRGB2XYZ_build( VipsObject *object ) -{ - VipsColourCode *code = (VipsColourCode *) object; - - if( code->in ) - code->input_format = - code->in->BandFmt == VIPS_FORMAT_USHORT ? - VIPS_FORMAT_USHORT : VIPS_FORMAT_UCHAR; - - if( VIPS_OBJECT_CLASS( vips_sRGB2XYZ_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - -static void -vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class ) -{ - VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); - - object_class->nickname = "sRGB2XYZ"; - object_class->description = _( "convert an sRGB image to XYZ" ); - object_class->build = vips_sRGB2XYZ_build; - - colour_class->process_line = vips_sRGB2XYZ_line; -} - -static void -vips_sRGB2XYZ_init( VipssRGB2XYZ *sRGB2XYZ ) -{ - VipsColour *colour = VIPS_COLOUR( sRGB2XYZ ); - VipsColourCode *code = VIPS_COLOUR_CODE( sRGB2XYZ ); - - colour->coding = VIPS_CODING_NONE; - colour->interpretation = VIPS_INTERPRETATION_XYZ; - colour->format = VIPS_FORMAT_FLOAT; - colour->bands = 3; - - code->input_coding = VIPS_CODING_NONE; - code->input_bands = 3; - - /* The default. This can get changed above ^^ if we see a - * 16-bit input. - */ - code->input_format = VIPS_FORMAT_UCHAR; -} - -/** - * 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/colour/sRGB2scRGB.c b/libvips/colour/sRGB2scRGB.c index cbd33475..e21bff42 100644 --- a/libvips/colour/sRGB2scRGB.c +++ b/libvips/colour/sRGB2scRGB.c @@ -1,7 +1,18 @@ /* Turn displayable rgb files to scRGB. * + * 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 + * 6/11/12 + * - add 16-bit sRGB import * 11/12/12 - * - from sRGB2XYZ.c + * - cut about to make sRGB2scRGB.c */ /* diff --git a/libvips/colour/scRGB2sRGB.c b/libvips/colour/scRGB2sRGB.c index 21857246..5fe373d9 100644 --- a/libvips/colour/scRGB2sRGB.c +++ b/libvips/colour/scRGB2sRGB.c @@ -1,7 +1,30 @@ /* Turn scRGB 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 + * 6/11/12 + * - added 16-bit option * 11/12/12 - * - from XYZ2sRGB.c + * - cut about to make scRGB2sRGB.c */ /* diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 3a03403b..60532b49 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -2495,7 +2495,7 @@ im_dE_fromdisp( IMAGE *im1, IMAGE *im2, IMAGE *out, struct im_col_display *d ) int im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d ) { - IMAGE *t[1]; + VipsImage *t[1]; if( im_open_local_array( out, t, 1, "im_disp2Lab:1", "p" ) || im_disp2XYZ( in, t[0], d ) || @@ -2508,15 +2508,13 @@ im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d ) int im_sRGB2XYZ( IMAGE *in, IMAGE *out ) { - VipsImage *x; + VipsImage **t = (VipsImage **) + vips_object_local_array( (VipsObject *) out, 2 ); - if( vips_sRGB2XYZ( in, &x, NULL ) ) + if( vips_sRGB2scRGB( in, &t[0], NULL ) || + vips_scRGB2XYZ( t[0], &t[1], NULL ) || + im_copy( t[1], out ) ) return( -1 ); - if( im_copy( x, out ) ) { - g_object_unref( x ); - return( -1 ); - } - g_object_unref( x ); return( 0 ); } @@ -2524,15 +2522,13 @@ im_sRGB2XYZ( IMAGE *in, IMAGE *out ) int im_XYZ2sRGB( IMAGE *in, IMAGE *out ) { - VipsImage *x; + VipsImage **t = (VipsImage **) + vips_object_local_array( (VipsObject *) out, 2 ); - if( vips_XYZ2sRGB( in, &x, NULL ) ) + if( vips_XYZ2scRGB( in, &t[0], NULL ) || + vips_scRGB2sRGB( t[0], &t[1], NULL ) || + im_copy( t[1], out ) ) return( -1 ); - if( im_copy( x, out ) ) { - g_object_unref( x ); - return( -1 ); - } - g_object_unref( x ); return( 0 ); } diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 8cefcc20..b1abce23 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -146,11 +146,6 @@ int vips_XYZ2scRGB( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_scRGB2sRGB( 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_sRGB2scRGB( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_scRGB2XYZ( VipsImage *in, VipsImage **out, ... ) From c5a600b286a5ff81f5b3831f37aa950c4b6585d8 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 13 Dec 2012 12:21:02 +0000 Subject: [PATCH 4/4] tag Radiance images as scRGB They aren't always, but scRGB is also 0-1 range, so conveniently this now works: vips copy car-stack-eighth.hdr x.jpg --- TODO | 2 ++ libvips/colour/rad2float.c | 7 +++++-- libvips/foreign/radiance.c | 4 +++- libvips/iofuncs/header.c | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 62c0b7e6..549c4828 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +- does radiance import give 0-1 RGB images? we could tag them as scRGB + - now we've removed round-to-nearest from NN, we need something extra in the affine transform to displace the input cods diff --git a/libvips/colour/rad2float.c b/libvips/colour/rad2float.c index 79cbe3bd..d34bf62d 100644 --- a/libvips/colour/rad2float.c +++ b/libvips/colour/rad2float.c @@ -1,10 +1,13 @@ /* Convert Radiance 32bit packed format to float. + * * 3/3/09 * - from LabQ2Lab and Radiance sources * 2/11/09 * - gtkdoc * 20/9/12 - * redo as a class + * - redo as a class + * 13/12/12 + * - tag output as scRGB, since it'll be 0-1 */ /* @@ -196,7 +199,7 @@ vips_rad2float_init( VipsRad2float *rad2float ) VipsColourCode *code = VIPS_COLOUR_CODE( rad2float ); colour->coding = VIPS_CODING_NONE; - colour->interpretation = VIPS_INTERPRETATION_sRGB; + colour->interpretation = VIPS_INTERPRETATION_scRGB; colour->format = VIPS_FORMAT_FLOAT; colour->bands = 3; diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index f829a223..a5221dde 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -6,6 +6,8 @@ * - add radiance write * 20/12/11 * - reworked as some fns ready for new-style classes + * 13/12/12 + * - tag RGB rad images as scRGB */ /* @@ -900,7 +902,7 @@ rad2vips_get_header( Read *read, FILE *fin, VipsImage *out ) vips_image_set_string( out, "rad-format", read->format ); if( strcmp( read->format, COLRFMT ) == 0 ) - out->Type = VIPS_INTERPRETATION_RGB; + out->Type = VIPS_INTERPRETATION_scRGB; else if( strcmp( read->format, CIEFMT ) == 0 ) out->Type = VIPS_INTERPRETATION_XYZ; else diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index ea9b93ec..400711b8 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -441,6 +441,7 @@ vips_image_guess_interpretation( const VipsImage *image ) case VIPS_INTERPRETATION_CMC: case VIPS_INTERPRETATION_LCH: case VIPS_INTERPRETATION_sRGB: + case VIPS_INTERPRETATION_scRGB: case VIPS_INTERPRETATION_YXY: if( image->Bands < 3 ) sane = FALSE;