redo im_UCS2LCh() and im_LCh2UCS() as classes
This commit is contained in:
parent
8abbcc4e77
commit
496b4373a4
@ -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
4
TODO
@ -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
223
libvips/colour/LCh2UCS.c
Normal 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 );
|
||||
}
|
@ -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
301
libvips/colour/UCS2LCh.c
Normal 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 );
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 ) );
|
||||
}
|
@ -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 ) );
|
||||
}
|
@ -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 );
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user