redo im_UCS2LCh() and im_LCh2UCS() as classes

This commit is contained in:
John Cupitt 2012-09-19 14:13:37 +01:00
parent 8abbcc4e77
commit 496b4373a4
12 changed files with 594 additions and 519 deletions

View File

@ -1,5 +1,6 @@
31/8/12 started 7.31.0
- redone im_Lab2XYZ(), im_Lab2LCh(), im_LCh2Lab() as classes
- redone im_Lab2XYZ(), im_Lab2LCh(), im_LCh2Lab(), im_UCS2LCh, im_LCh2UCS()
as classes
13/9/12 started 7.30.3
- linecache sized itself too large

4
TODO
View File

@ -1,3 +1,7 @@
- see comment on make_CI() -- investigate
add l:c args
- can we make DOUBLE ARRAY args easier from C?
at the moment they are horrible or ad-hoc, see vips_linear() etc. and

223
libvips/colour/LCh2UCS.c Normal file
View File

@ -0,0 +1,223 @@
/* im_LCh2UCS
*
* Modified:
* 2/11/09
* - gtkdoc
* 19/9/12
* - redone 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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include "colour.h"
typedef VipsColorimetric VipsLCh2UCS;
typedef VipsColorimetricClass VipsLCh2UCSClass;
G_DEFINE_TYPE( VipsLCh2UCS, vips_LCh2UCS, VIPS_TYPE_COLORIMETRIC );
/* Constants for Lucs.
*/
#define c1 21.75
#define c2 0.3838
#define c3 38.54
/**
* vips_col_L2Lucs:
* @L: CIE L*
*
* Calculate Lucs from L.
*
* Returns: Lucs
*/
float
vips_col_L2Lucs( float L )
{
float Lucs;
if( L >= 16.0 )
Lucs = (c1 * log( L ) + c2 * L - c3);
else
Lucs = 1.744 * L;
return( Lucs );
}
/* Constants for Cucs.
*/
#define c4 0.162
#define c5 10.92
#define c6 0.638
#define c7 0.07216
#define c8 4.907
/**
* vips_col_C2Cucs:
* @C: Chroma
*
* Calculate Cucs from C.
*
* Returns: Cucs.
*/
float
vips_col_C2Cucs( float C )
{
float Cucs;
Cucs = c4 * C + c5 * log( c6 + c7 * C ) + c8;
if( Cucs < 0 )
Cucs = 0;
return( Cucs );
}
/**
* vips_col_Ch2hucs:
* @C: Chroma
* @h: Hue (degrees)
*
* Calculate hucs from C and h.
*
* Returns: hucs.
*/
float
vips_col_Ch2hucs( float C, float h )
{
float P, D, f, g;
float k4, k5, k6, k7, k8;
float hucs;
if( h < 49.1 ) {
k4 = 133.87;
k5 = -134.5;
k6 = -.924;
k7 = 1.727;
k8 = 340.0;
}
else if( h < 110.1 ) {
k4 = 11.78;
k5 = -12.7;
k6 = -.218;
k7 = 2.12;
k8 = 333.0;
}
else if( h < 269.6 ) {
k4 = 13.87;
k5 = 10.93;
k6 = 0.14;
k7 = 1.0;
k8 = -83.0;
}
else {
k4 = .14;
k5 = 5.23;
k6 = .17;
k7 = 1.61;
k8 = 233.0;
}
P = cos( VIPS_RAD( k8 + k7 * h ) );
D = k4 + k5 * P * pow( fabs( P ), k6 );
g = C * C * C * C;
f = sqrt( g / (g + 1900.0) );
hucs = h + D * f;
return( hucs );
}
static void
vips_LCh2UCS_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
{
float *p = (float *) in[0];
float *q = (float *) out;
int x;
for( x = 0; x < width; x++ ) {
float L = p[0];
float C = p[1];
float h = p[2];
p += 3;
q[0] = vips_col_L2Lucs( L );
q[1] = vips_col_C2Cucs( C );
q[2] = vips_col_Ch2hucs( C, h );
q += 3;
}
}
static void
vips_LCh2UCS_class_init( VipsLCh2UCSClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class );
object_class->nickname = "LCh2UCS";
object_class->description = _( "transform LCh to UCS" );
colour_class->process_line = vips_LCh2UCS_line;
colour_class->interpretation = VIPS_INTERPRETATION_UCS;
}
static void
vips_LCh2UCS_init( VipsLCh2UCS *LCh2UCS )
{
}
/**
* vips_LCh2UCS:
* @in: input image
* @out: output image
*
* Turn LCh to UCS.
*
* Returns: 0 on success, -1 on error
*/
int
vips_LCh2UCS( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "LCh2UCS", ap, in, out );
va_end( ap );
return( result );
}

View File

@ -8,9 +8,10 @@ libcolour_la_SOURCES = \
derived.c \
Lab2XYZ.c \
Lab2LCh.c \
im_icc_transform.c \
LCh2Lab.c \
im_LCh2UCS.c \
LCh2UCS.c \
UCS2LCh.c \
im_icc_transform.c \
im_Lab2LabQ.c \
im_Lab2LabS.c \
im_LabQ2Lab.c \
@ -19,7 +20,6 @@ libcolour_la_SOURCES = \
im_LabS2LabQ.c \
im_LabS2Lab.c \
im_lab_morph.c \
im_UCS2LCh.c \
im_XYZ2Lab.c \
im_XYZ2Yxy.c \
im_float2rad.c \

301
libvips/colour/UCS2LCh.c Normal file
View File

@ -0,0 +1,301 @@
/* Turn UCS to LCh
*
* 15/11/94 JC
* - error messages added
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrap_oneonebuf() now
* 2/11/09
* - gtkdoc
* 30/11/09
* - argh, im_col_make_tables_UCS(); missing, thanks Peter
* 19/9/12
* - redone 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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include "colour.h"
/* Arrays for lookup tables for the inverse function.
*/
static float LI[1001];
static float CI[3001];
static float hI[101][361];
typedef VipsColorimetric VipsUCS2LCh;
typedef VipsColorimetricClass VipsUCS2LChClass;
G_DEFINE_TYPE( VipsUCS2LCh, vips_UCS2LCh, VIPS_TYPE_COLORIMETRIC );
/* Generate LI (inverse) tables.
*/
static void
make_LI( void )
{
int i;
float Ll[ 1001 ];
int j;
for( i = 0; i < 1001; i++ )
Ll[i] = vips_col_L2Lucs( i / 10.0 );
for( j = 0, i = 0; i < 1001; i++ ) {
while( Ll[j] <= i / 10.0 && j < 1001 )
j++;
LI[i] = (j - 1) / 10.0 +
(i / 10.0 - Ll[j - 1]) / ((Ll[j] - Ll[j - 1]) * 10.0);
}
}
/* Generate Cucs table.
*/
static void
make_CI( void )
{
int i;
float Cl[3001];
for( i = 0; i < 3001; i++ )
Cl[i] = vips_col_C2Cucs( i / 10.0 );
for( i = 0; i < 3001; i++ ) {
int j;
/*
*
why isn't this loop the same as the one for L above
or for h below
*/
for( j = 0; j < 3001 && Cl[j] <= i / 10.0; j++ )
;
CI[i] = (j - 1) / 10.0 +
(i / 10.0 - Cl[j - 1]) / ((Cl[j] - Cl[j - 1]) * 10.0);
}
}
/* The difficult one: hucs.
*/
static void
make_hI( void )
{
int i, j, k;
float hl[101][361];
for( i = 0; i < 361; i++ )
for( j = 0; j < 101; j++ )
hl[j][i] = vips_col_Ch2hucs( j * 2.0, i );
for( j = 0; j < 101; j++ ) {
k = 0;
for( i = 0; i < 361; i++ ) {
while( k < 361 && hl[j][k] <= i )
k++;
hI[j][i] = k - 1 + (i - hl[j][k - 1]) /
(hl[j][k] - hl[j][k - 1]);
}
}
}
/**
* vips_col_Lucs2L:
* @Lucs: L ucs
*
* Calculate L from Lucs using a table. Call vips_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: L*
*/
float
vips_col_Lucs2L( float Lucs )
{
int known; /* nearest input value in the table, <= Lucs */
known = floor( Lucs * 10.0 );
known = VIPS_CLIP( 0, known, 1000 );
return( LI[known] +
(LI[known + 1] - LI[known]) * (Lucs * 10.0 - known) );
}
/**
* vips_col_Cucs2C:
* @Cucs: Cucs
*
* Calculate C from Cucs using a table.
* Call vips_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: C.
*/
float
vips_col_Cucs2C( float Cucs )
{
int known; /* nearest input value in the table, <= Cucs */
known = floor( Cucs * 10.0 );
known = VIPS_CLIP( 0, known, 3000 );
return( CI[known] +
(CI[known + 1] - CI[known]) * (Cucs * 10.0 - known) );
}
/**
* vips_col_Chucs2h:
* @C: Chroma
* @hucs: Hue ucs (degrees)
*
* Calculate h from C and hucs, using a table.
* Call vips_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: h.
*/
float
vips_col_Chucs2h( float C, float hucs )
{
int r, known; /* nearest input value in the table, <= hucs */
/* Which row of the table?
*/
r = (int) ((C + 1.0) / 2.0);
r = VIPS_CLIP( 0, r, 100 );
known = floor( hucs );
known = VIPS_CLIP( 0, known, 360 );
return( hI[r][known] +
(hI[r][(known + 1) % 360] - hI[r][known]) * (hucs - known) );
}
static void *
tables_init( void *client )
{
make_LI();
make_CI();
make_hI();
return( NULL );
}
/**
* vips_col_make_tables_UCS:
*
* Make the lookup tables for ucs.
*/
void
vips_col_make_tables_UCS( void )
{
static GOnce once = G_ONCE_INIT;
(void) g_once( &once, tables_init, NULL );
}
/* Process a buffer of data.
*/
void
vips_UCS2LCh_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
{
float *p = (float *) in[0];
float *q = (float *) out;
int x;
for( x = 0; x < width; x++ ) {
float Lucs = p[0];
float Cucs = p[1];
float hucs = p[2];
/* Turn from UCS.
*/
float C = vips_col_Cucs2C( Cucs );
float h = vips_col_Chucs2h( C, hucs );
float L = vips_col_Lucs2L( Lucs );
p += 3;
q[0] = L;
q[1] = C;
q[2] = h;
q += 3;
}
}
static void
vips_UCS2LCh_class_init( VipsUCS2LChClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class );
object_class->nickname = "UCS2LCh";
object_class->description = _( "transform LCh to UCS" );
colour_class->process_line = vips_UCS2LCh_line;
colour_class->interpretation = VIPS_INTERPRETATION_LCH;
}
static void
vips_UCS2LCh_init( VipsUCS2LCh *UCS2LCh )
{
vips_col_make_tables_UCS();
}
/**
* vips_UCS2LCh:
* @in: input image
* @out: output image
*
* Turn LCh to UCS.
*
* Returns: 0 on success, -1 on error
*/
int
vips_UCS2LCh( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "UCS2LCh", ap, in, out );
va_end( ap );
return( result );
}

View File

@ -246,8 +246,12 @@ vips_colour_operation_init( void )
extern GType vips_Lab2XYZ_get_type( void );
extern GType vips_Lab2LCh_get_type( void );
extern GType vips_LCh2Lab_get_type( void );
extern GType vips_LCh2UCS_get_type( void );
extern GType vips_UCS2LCh_get_type( void );
vips_Lab2XYZ_get_type();
vips_Lab2LCh_get_type();
vips_LCh2Lab_get_type();
vips_LCh2UCS_get_type();
vips_UCS2LCh_get_type();
}

View File

@ -67,16 +67,6 @@
#include <vips/vips.h>
#include <vips/internal.h>
/* Have the tables been made?
*/
static int made_ucs_tables = 0;
/* Arrays for lookup tables.
*/
static float LI[ 1001 ];
static float CI[ 3001 ];
static float hI[ 101 ][ 361 ];
/**
* im_col_XYZ2Lab:
* @X: Input CIE XYZ colour
@ -132,325 +122,6 @@ im_col_pythagoras( float L1, float a1, float b1, float L2, float a2, float b2 )
/* Functions to convert from Lab to uniform colour space and back.
*/
/* Constants for Lucs.
*/
#define c1 21.75
#define c2 0.3838
#define c3 38.54
/**
* im_col_L2Lucs:
* @L: CIE L*
*
* Calculate Lucs from L.
*
* Returns: Lucs
*/
float
im_col_L2Lucs( float L )
{
float Lucs;
if( L >= 16.0 )
Lucs = (c1 * log( L ) + c2 * L - c3);
else
Lucs = 1.744 * L;
return( Lucs );
}
/* Generate Ll and LI (inverse) tables. Don't call the above for speed.
*/
static void
make_LI( void )
{
int i, j=0;
float L, Ll[ 1001 ];
for( i = 0; i < 1001; i++ )
{
L = i / 10.0;
if( L >= 16.0 )
Ll[ i ] = (c1 * log( L ) + c2 * L - c3);
else
Ll[ i ] = 1.744 * L;
}
for( i = 0; i < 1001; i++ )
{
while ( (Ll[j]<=i/10.0) && ( j<1001) ) j++;
LI[i] = (j-1)/10.0 + (i/10.0-Ll[j-1]) / ((Ll[j]-Ll[j-1])*10.0);
}
}
/**
* im_col_Lucs2L:
* @Lucs: L ucs
*
* Calculate L from Lucs using a table. Call im_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: L*
*/
float
im_col_Lucs2L( float Lucs )
{
int known; /* nearest input value in the table, <= Lucs */
known = floor(Lucs*10.0);
if( known < 0 )
known = 0;
if( known > 1000 )
known = 1000;
return( LI[known] + (LI[known+1]-LI[known])*(Lucs*10.0-known) );
}
/* Constants for Cucs.
*/
#define c4 0.162
#define c5 10.92
#define c6 0.638
#define c7 0.07216
#define c8 4.907
/**
* im_col_C2Cucs:
* @C: Chroma
*
* Calculate Cucs from C.
*
* Returns: Cucs.
*/
float
im_col_C2Cucs( float C )
{
float Cucs;
Cucs = (c4 * C + c5 * (log( c6 + c7 * C )) + c8);
if ( Cucs<0 ) Cucs = 0;
return( Cucs );
}
/* Generate Cucs table. Again, inline the code above.
*/
static void
make_CI( void )
{
int i;
float C;
float Cl[3001];
for( i = 0; i < 3001; i++ ) {
C = i / 10.0;
Cl[i] = (c4 * C + c5 * (log( c6 + c7 * C )) + c8);
}
for( i = 0; i < 3001; i++ ) {
int j;
for( j = 0; j < 3001 && Cl[j] <= i / 10.0; j++ )
;
CI[i] = (j - 1) / 10.0 +
(i / 10.0 - Cl[j - 1]) / ((Cl[j] - Cl[j - 1]) * 10.0);
}
}
/**
* im_col_Cucs2C:
* @Cucs: Cucs
*
* Calculate C from Cucs using a table.
* Call im_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: C.
*/
float
im_col_Cucs2C( float Cucs )
{
int known; /* nearest input value in the table, <= Cucs */
known = floor(Cucs*10.0);
if( known < 0 )
known = 0;
if( known > 3000 )
known = 3000;
return( CI[known] + (CI[known+1]-CI[known])*(Cucs*10.0-known) );
}
/**
* im_col_Ch2hucs:
* @C: Chroma
* @h: Hue (degrees)
*
* Calculate hucs from C and h.
*
* Returns: hucs.
*/
float
im_col_Ch2hucs( float C, float h )
{
float P, D, f, g;
float k4, k5, k6, k7, k8;
float hucs;
if( h < 49.1 ) {
k4 = 133.87;
k5 = -134.5;
k6 = -.924;
k7 = 1.727;
k8 = 340.0;
}
else if( h < 110.1 ) {
k4 = 11.78;
k5 = -12.7;
k6 = -.218;
k7 = 2.12;
k8 = 333.0;
}
else if( h < 269.6 ) {
k4 = 13.87;
k5 = 10.93;
k6 = 0.14;
k7 = 1.0;
k8 = -83.0;
}
else {
k4 = .14;
k5 = 5.23;
k6 = .17;
k7 = 1.61;
k8 = 233.0;
}
P = cos( IM_RAD( k8 + k7 * h ) );
D = k4 + k5 * P * pow( fabs( P ), k6 );
g = C * C * C * C;
f = sqrt( g / (g + 1900.0) );
hucs = h + D * f;
return( hucs );
}
/* The difficult one: hucs. Again, inline.
*/
static void
make_hI( void )
{
int i, j, k;
float P, D, C, f, hl[101][361];
float k4, k5, k6, k7, k8;
for( i = 0; i < 361; i++ ) {
if( i < 49.1 ) {
k4 = 133.87;
k5 = -134.5;
k6 = -.924;
k7 = 1.727;
k8 = 340.0;
}
else if( i < 110.1 ) {
k4 = 11.78;
k5 = -12.7;
k6 = -.218;
k7 = 2.12;
k8 = 333.0;
}
else if( i < 269.6 ) {
k4 = 13.87;
k5 = 10.93;
k6 = 0.14;
k7 = 1.0;
k8 = -83.0;
}
else {
k4 = .14;
k5 = 5.23;
k6 = .17;
k7 = 1.61;
k8 = 233.0;
}
P = cos( IM_RAD( k8 + k7 * i ) );
D = k4 + k5 * P * pow( fabs( P ), k6 );
for( j = 0; j < 101; j++ ) {
float g;
C = j * 2.0;
g = C * C * C * C;
f = sqrt( g / (g + 1900.0) );
hl[j][i] = i + D * f;
}
}
for( j = 0; j < 101; j++ ) {
k = 0;
for( i = 0; i < 361; i++ ) {
while( k < 361 && hl[j][k] <= i )
k++;
hI[j][i] = k - 1 + (i - hl[j][k - 1]) /
(hl[j][k] - hl[j][k - 1]);
}
}
}
/**
* im_col_Chucs2h:
* @C: Chroma
* @hucs: Hue ucs (degrees)
*
* Calculate h from C and hucs, using a table.
* Call im_col_make_tables_UCS() at
* least once before using this function.
*
* Returns: h.
*/
float
im_col_Chucs2h( float C, float hucs )
{
int r, known; /* nearest input value in the table, <= hucs */
/* Which row of the table?
*/
r = (int) ((C + 1.0) / 2.0);
if( r < 0 )
r = 0;
if( r > 100 )
r = 100;
known = floor( hucs );
if( known < 0 )
known = 0;
if( known > 360 )
known = 360;
return( hI[r][known] +
(hI[r][(known + 1) % 360] - hI[r][known]) * (hucs - known) );
}
/**
* im_col_make_tables_UCS:
*
* Make the lookup tables for ucs.
*/
void
im_col_make_tables_UCS( void )
{
if( !made_ucs_tables ) {
make_LI();
make_CI();
make_hI();
made_ucs_tables = -1;
}
}
/**
* im_col_dECMC:
* @L1: Input coordinate 1

View File

@ -1,81 +0,0 @@
/* im_LCh2UCS
*
* Modified:
* 2/11/09
* - gtkdoc
*/
/*
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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
/* Our main loop.
*/
void
imb_LCh2UCS( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float L = p[0];
float C = p[1];
float h = p[2];
p += 3;
/* Turn to UCS.
*/
q[0] = im_col_L2Lucs( L );
q[1] = im_col_C2Cucs( C );
q[2] = im_col_Ch2hucs( C, h );
q += 3;
}
}
/**
* im_LCh2UCS:
* @in: input image
* @out: output image
*
* Turn LCh to UCS.
*
* Returns: 0 on success, -1 on error.
*/
int
im_LCh2UCS( IMAGE *in, IMAGE *out )
{
return( im__colour_unary( "im_LCh2UCS", in, out, IM_TYPE_UCS,
(im_wrapone_fn) imb_LCh2UCS, NULL, NULL ) );
}

View File

@ -1,94 +0,0 @@
/* Turn UCS to LCh
*
* 15/11/94 JC
* - error messages added
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrap_oneonebuf() now
* 2/11/09
* - gtkdoc
* 30/11/09
* - argh, im_col_make_tables_UCS(); missing, thanks Peter
*/
/*
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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
/* Process a buffer of data.
*/
void
imb_UCS2LCh( float *p, float *q, int n )
{
int x;
for( x = 0; x < n; x++ ) {
float Lucs = p[0];
float Cucs = p[1];
float hucs = p[2];
/* Turn from UCS.
*/
float C = im_col_Cucs2C( Cucs );
float h = im_col_Chucs2h( C, hucs );
float L = im_col_Lucs2L( Lucs );
p += 3;
q[0] = L;
q[1] = C;
q[2] = h;
q += 3;
}
}
/**
* im_UCS2LCh:
* @in: input image
* @out: output image
*
* Turn UCS to LCh.
*
* Returns: 0 on success, -1 on error.
*/
int
im_UCS2LCh( IMAGE *in, IMAGE *out )
{
im_col_make_tables_UCS();
return( im__colour_unary( "im_UCS2LCh", in, out, IM_TYPE_LCH,
(im_wrapone_fn) imb_UCS2LCh, NULL, NULL ) );
}

View File

@ -2217,3 +2217,35 @@ im_LCh2Lab( IMAGE *in, IMAGE *out )
return( 0 );
}
int
im_LCh2UCS( IMAGE *in, IMAGE *out )
{
VipsImage *x;
if( vips_LCh2UCS( in, &x, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}
int
im_UCS2LCh( IMAGE *in, IMAGE *out )
{
VipsImage *x;
if( vips_UCS2LCh( in, &x, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}

View File

@ -120,6 +120,10 @@ int vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... )
int vips_XYZ2disp( VipsImage *in, VipsImage **out,
struct im_col_display *disp, ... )
__attribute__((sentinel));
int vips_LCh2UCS( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_UCS2LCh( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
void vips_col_Lab2XYZ( float L, float a, float b,
float *X, float *Y, float *Z );
@ -127,6 +131,15 @@ double vips_col_ab2h( double a, double b );
void vips_col_ab2Ch( float a, float b, float *C, float *h );
void vips_col_Ch2ab( float C, float h, float *a, float *b );
float vips_col_L2Lucs( float L );
float vips_col_C2Cucs( float C );
float vips_col_Ch2hucs( float C, float h );
void vips_col_make_tables_UCS( void );
float vips_col_Lucs2L( float Lucs );
float vips_col_Cucs2C( float Cucs );
float vips_col_Chucs2h( float C, float hucs );
@ -138,14 +151,6 @@ void im_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b );
float im_col_pythagoras( float L1, float a1, float b1,
float L2, float a2, float b2 );
void im_col_make_tables_UCS( void );
float im_col_L2Lucs( float L );
float im_col_Lucs2L( float Lucs );
float im_col_C2Cucs( float C );
float im_col_Cucs2C( float Cucs );
float im_col_Ch2hucs( float C, float h );
float im_col_Chucs2h( float C, float hucs );
float im_col_dECMC(
float L1, float a1, float b1, float L2, float a2, float b2 );
@ -155,17 +160,15 @@ float im_col_dE00(
int im_LabQ2XYZ( VipsImage *in, VipsImage *out );
int im_rad2float( VipsImage *in, VipsImage *out );
int im_float2rad( VipsImage *in, VipsImage *out );
int im_LCh2UCS( VipsImage *in, VipsImage *out );
int im_Lab2LabQ( VipsImage *in, VipsImage *out );
int im_Lab2LabS( VipsImage *in, VipsImage *out );
int im_Lab2UCS( VipsImage *in, VipsImage *out );
int im_LabQ2Lab( VipsImage *in, VipsImage *out );
int im_LabQ2LabS( VipsImage *in, VipsImage *out );
int im_LabS2LabQ( VipsImage *in, VipsImage *out );
int im_LabS2Lab( VipsImage *in, VipsImage *out );
int im_UCS2XYZ( VipsImage *in, VipsImage *out );
int im_UCS2LCh( VipsImage *in, VipsImage *out );
int im_UCS2Lab( VipsImage *in, VipsImage *out );
int im_Lab2UCS( VipsImage *in, VipsImage *out );
int im_XYZ2Lab( VipsImage *in, VipsImage *out );
int im_XYZ2Lab_temp( VipsImage *in, VipsImage *out,
double X0, double Y0, double Z0 );

View File

@ -85,6 +85,15 @@ extern "C" {
#define im_col_ab2Ch vips_col_ab2Ch
#define im_col_Ch2ab vips_col_Ch2ab
#define im_col_L2Lucs vips_col_L2Lucs
#define im_col_C2Cucs vips_col_C2Cucs
#define im_col_Ch2hucs vips_col_Ch2hucs
#define im_col_make_tables_UCS vips_col_make_tables_UCS
#define im_col_Lucs2L vips_col_Lucs2L
#define im_col_Cucs2C vips_col_Cucs2C
#define im_col_Chucs2h vips_col_Chucs2h
#define PEL VipsPel
#define IM_BANDFMT_NOTSET VIPS_FORMAT_NOTSET
@ -701,6 +710,8 @@ int im_Lab2XYZ_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 );
int im_Lab2XYZ( IMAGE *in, IMAGE *out );
int im_Lab2LCh( VipsImage *in, VipsImage *out );
int im_LCh2Lab( VipsImage *in, VipsImage *out );
int im_LCh2UCS( VipsImage *in, VipsImage *out );
int im_UCS2LCh( VipsImage *in, VipsImage *out );
/* ruby-vips uses this
*/