This commit is contained in:
John Cupitt 2009-11-01 21:28:49 +00:00
parent 4c1dd0f711
commit d17691ea0c
16 changed files with 186 additions and 166 deletions

View File

@ -70,6 +70,7 @@
- added im_insertplaceset()
- im_insertplace() allows small to be outside big
- added im__colour_binary(), colour ops now work on any image format
- added im_col_display_get_table(), so display tables are now shared by name
25/3/09 started 7.18.0
- revised version numbers

4
TODO
View File

@ -1,7 +1,3 @@
- im_disp2XYZ() makes a new set of lookup tables for every call, argh
maybe use disp->name to get built tables from a hash? I think we can say
names need to be unique
- more stuff from util.c? too much to do it all now

View File

@ -40,6 +40,7 @@
#include <ctype.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
@ -57,6 +58,10 @@
* but most programs will be better off with im_icc_transform() and friends.
*/
/* Tables we've generated, indexed by display name.
*/
static GHashTable *im__col_display_tables = NULL;
/* Values for IM_TYPE_sRGB.
*/
static struct im_col_display srgb_profile = {
@ -341,6 +346,9 @@ im_col_make_tables_RGB( IMAGE *im, struct im_col_display *d )
double **temp;
int i, j;
printf( "im_col_make_tables_RGB: generating table for %s\n",
d->d_name );
if( !(table = IM_NEW( im, struct im_col_tab_disp )) )
return( NULL );
@ -370,15 +378,35 @@ im_col_make_tables_RGB( IMAGE *im, struct im_col_display *d )
return( table );
}
struct im_col_tab_disp *
im_col_display_get_table( struct im_col_display *d )
{
struct im_col_tab_disp *table;
if( !im__col_display_tables )
im__col_display_tables = g_hash_table_new(
g_str_hash, g_str_equal );
if( !(table = g_hash_table_lookup( im__col_display_tables,
d->d_name )) ) {
table = im_col_make_tables_RGB( NULL, d );
g_hash_table_insert( im__col_display_tables, d->d_name, table );
}
return( table );
}
/* Computes the transform: r,g,b => Yr,Yg,Yb. It finds Y values in
* lookup tables and calculates X, Y, Z.
*/
int
im_col_rgb2XYZ( struct im_col_display *d, struct im_col_tab_disp *table,
im_col_rgb2XYZ( struct im_col_display *d,
int r, int g, int b, float *X, float *Y, float *Z )
{
float Yr, Yg, Yb;
struct im_col_tab_disp *table = im_col_display_get_table( d );
float *mat = &table->mat_lum2XYZ[0][0];
float Yr, Yg, Yb;
int i;
if( r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 ) {
@ -425,12 +453,13 @@ im_col_rgb2XYZ( struct im_col_display *d, struct im_col_tab_disp *table,
* contain an approximation of the right colour.
*/
int
im_col_XYZ2rgb( struct im_col_display *d, struct im_col_tab_disp *table,
float X, float Y, float Z,
int *r_ret, int *g_ret, int *b_ret,
im_col_XYZ2rgb( struct im_col_display *d,
float X, float Y, float Z, int *r_ret, int *g_ret, int *b_ret,
int *or_ret )
{
struct im_col_tab_disp *table = im_col_display_get_table( d );
float *mat = &table->mat_XYZ2lum[0][0];
int or = 0; /* Out of range flag */
float Yr, Yg, Yb;

View File

@ -1,12 +1,4 @@
/* @(#) Turn Lab to LCh
* @(#)
* @(#) Usage:
* @(#) im_Lab2LCh( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* Turn Lab to LCh
*/
/*
@ -75,29 +67,46 @@ imb_Lab2LCh( float *p, float *q, int n )
}
}
int
im_Lab2LCh( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_Lab2LCh", "%s",
_( "3-band uncoded float input only" ) );
return( -1 );
}
int
im__colour_unary( const char *domain,
IMAGE *in, IMAGE *out,
im_wrapone_fn buffer_fn, void *a, void *b )
{
IMAGE *t[1];
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
if( im_check_uncoded( domain, in ) ||
im_check_bands( domain, in, 3 ) ||
im_open_local_array( out, t, 1, domain, "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
return( -1 );
out->Type = IM_TYPE_LCH;
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Lab2LCh, NULL, NULL ) )
if( im_cp_desc( out, t[0] ) )
return( -1 );
if( im_wrapone( t[0], out,
(im_wrapone_fn) buffer_fn, a, b ) )
return( -1 );
return( 0 );
}
/**
* im_Lab2LCh:
* @in: input image
* @out: output image
*
* Turn Lab to LCh.
*
* Returns: 0 on success, -1 on error.
*/
int
im_Lab2LCh( IMAGE *in, IMAGE *out )
{
if( im__colour_unary( "im_Lab2LCh", in, out,
(im_wrapone_fn) imb_Lab2LCh, NULL, NULL ) )
return( -1 );
out->Type = IM_TYPE_LCH;
return( 0 );
}

View File

@ -25,6 +25,9 @@
* - go int earlier for speed up
* 20/6/02 JC
* - oops, were not clipping a/b range correctly
* 1/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -125,34 +128,24 @@ imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n )
}
int
im_Lab2LabQ( IMAGE *labim, IMAGE *outim )
im_Lab2LabQ( IMAGE *in, IMAGE *out )
{
/* Check for uncoded Lab type
*/
if( labim->Coding != IM_CODING_NONE ) {
im_error( "im_Lab2LabQ", "%s",
_( "uncoded input only" ) );
return( -1 );
}
if( labim->BandFmt != IM_BANDFMT_FLOAT || labim->Bands != 3 ) {
im_error( "im_Lab2LabQ", "%s",
_( "three-band float input only" ) );
return( -1 );
}
IMAGE *t[1];
/* Set up output image.
*/
if( im_cp_desc( outim, labim ) )
if( im_check_uncoded( "im_Lab2LabQ", in ) ||
im_check_bands( "im_Lab2LabQ", in, 3 ) ||
im_open_local_array( out, t, 1, "im_Lab2LabQ", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
return( -1 );
outim->Bands = 4;
outim->Type = IM_TYPE_LAB;
outim->BandFmt = IM_BANDFMT_UCHAR;
outim->Bbits = 8;
outim->Coding = IM_CODING_LABQ;
/* Process.
*/
if( im_wrapone( labim, outim,
if( im_cp_desc( out, t[0] ) )
return( -1 );
out->Bands = 4;
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Coding = IM_CODING_LABQ;
if( im_wrapone( t[0], out,
(im_wrapone_fn) imb_Lab2LabQ, NULL, NULL ) )
return( -1 );

View File

@ -1,6 +1,10 @@
/* @(#) im_Lab2LabS: quantise FLOAT Lab image into signed short format
/* im_Lab2LabS: quantise FLOAT Lab image into signed short format
*
* 12/12/02 JC
* - from im_Lab2LabQ
* 1/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -60,33 +64,33 @@ imb_Lab2LabS( float *in, signed short *out, int n )
}
}
/**
* im_Lab2LabS:
* @in: input image
* @out: output image
*
* Turn Lab to LabS, signed 16-bit int fixed point.
*
* Returns: 0 on success, -1 on error.
*/
int
im_Lab2LabS( IMAGE *labim, IMAGE *outim )
im_Lab2LabS( IMAGE *in, IMAGE *out )
{
/* Check for uncoded Lab type
*/
if( labim->Coding != IM_CODING_NONE ) {
im_error( "im_Lab2LabS", "%s",
_( "uncoded input only" ) );
return( -1 );
}
if( labim->BandFmt != IM_BANDFMT_FLOAT || labim->Bands != 3 ) {
im_error( "im_Lab2LabS", "%s",
_( "three-band float input only" ) );
return( -1 );
}
IMAGE *t[1];
/* Set up output image.
*/
if( im_cp_desc( outim, labim ) )
if( im_check_uncoded( "im_Lab2LabS", in ) ||
im_check_bands( "im_Lab2LabS", in, 3 ) ||
im_open_local_array( out, t, 1, "im_Lab2LabS", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
return( -1 );
outim->Type = IM_TYPE_LABS;
outim->BandFmt = IM_BANDFMT_SHORT;
outim->Bbits = IM_BBITS_SHORT;
/* Process.
*/
if( im_wrapone( labim, outim,
if( im_cp_desc( out, t[0] ) )
return( -1 );
out->Type = IM_TYPE_LABS;
out->BandFmt = IM_BANDFMT_SHORT;
out->Bbits = IM_BBITS_SHORT;
if( im_wrapone( t[0], out,
(im_wrapone_fn) imb_Lab2LabS, NULL, NULL ) )
return( -1 );

View File

@ -59,7 +59,6 @@
*/
typedef struct {
struct im_col_display *disp;
struct im_col_tab_disp *dtab;
PEL red[ 64 * 64 * 64 ];
PEL green[ 64 * 64 * 64 ];
PEL blue[ 64 * 64 * 64 ];
@ -130,11 +129,6 @@ im_LabQ2disp_build_table( IMAGE *out, struct im_col_display *d )
if( !(cal = IM_NEW( out, CalibrateInfo )) )
return( NULL );
cal->disp = d;
if( !(cal->dtab = im_col_make_tables_RGB( out, d ) ) ) {
if( !out )
im_free( cal );
return( NULL );
}
/* Build our tables.
*/
@ -156,7 +150,7 @@ im_LabQ2disp_build_table( IMAGE *out, struct im_col_display *d )
/* Convert to display.
*/
im_col_XYZ2rgb( cal->disp, cal->dtab,
im_col_XYZ2rgb( cal->disp,
X, Y, Z, &rb, &gb, &bb, &oflow );
/* Save RGB.

View File

@ -68,14 +68,15 @@
/* Process a buffer of data.
*/
void
imb_XYZ2disp( float *p, PEL *q, int n,
struct im_col_tab_disp *table, struct im_col_display *d )
{
int x;
imb_XYZ2disp( float *p, PEL *q, int n, struct im_col_display *d )
{
struct im_col_tab_disp *table = im_col_display_get_table( d );
float rstep = (d->d_YCR - d->d_Y0R) / 1500.0;
float gstep = (d->d_YCG - d->d_Y0G) / 1500.0;
float bstep = (d->d_YCB - d->d_Y0B) / 1500.0;
int x;
for( x = 0; x < n; x++ ) {
float Yr, Yg, Yb;
int i;
@ -133,8 +134,6 @@ imb_XYZ2disp( float *p, PEL *q, int n,
int
im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
struct im_col_tab_disp *table;
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
@ -150,15 +149,10 @@ im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
out->BandFmt = IM_BANDFMT_UCHAR;
out->Type = IM_TYPE_RGB;
/* Build the lookup tables
*/
if( !(table = im_col_make_tables_RGB( out, d )) )
return( -1 );
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2disp, table, d ) )
(im_wrapone_fn) imb_XYZ2disp, d, NULL ) )
return( -1 );
return( 0 );

View File

@ -45,11 +45,11 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* An n-input colour operation. Cast the inputs to three-band float and call.
/* A colour difference operation.
*/
int
im__colour_binary( const char *domain,
IMAGE *in1, IMAGE *in2, int bands, IMAGE *out,
im__colour_difference( const char *domain,
IMAGE *in1, IMAGE *in2, IMAGE *out,
im_wrapmany_fn buffer_fn, void *a, void *b )
{
IMAGE *t[3];
@ -66,7 +66,8 @@ im__colour_binary( const char *domain,
if( im_cp_descv( out, t[0], t[1], NULL ) )
return( -1 );
out->Bands = bands;
out->Bands = 1;
out->Type = IM_TYPE_B_W;
t[2] = NULL;
if( im_wrapmany( t, out, buffer_fn, a, b ) )
@ -112,12 +113,7 @@ imb_dE00_fromLab( float **p, float *q, int n )
int
im_dE00_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
if( im__colour_binary( "im_dE00_fromLab",
in1, in2, 1, out,
(im_wrapmany_fn) imb_dE00_fromLab, NULL, NULL ) )
return( -1 );
out->Type = IM_TYPE_B_W;
return( 0 );
return( im__colour_difference( "im_dE00_fromLab",
in1, in2, out,
(im_wrapmany_fn) imb_dE00_fromLab, NULL, NULL ) );
}

View File

@ -82,12 +82,7 @@ imb_dECMC_fromLab( float **p, float *q, int n )
int
im_dECMC_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
if( im__colour_binary( "im_dECMC_fromLab",
in1, in2, 1, out,
(im_wrapmany_fn) imb_dECMC_fromLab, NULL, NULL ) )
return( -1 );
out->Type = IM_TYPE_B_W;
return( 0 );
return( im__colour_difference( "im_dECMC_fromLab",
in1, in2, out,
(im_wrapmany_fn) imb_dECMC_fromLab, NULL, NULL ) );
}

View File

@ -77,12 +77,7 @@ imb_dE_fromLab( float **p, float *q, int n )
int
im_dE_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
if( im__colour_binary( "im_dE_fromLab",
in1, in2, 1, out,
(im_wrapmany_fn) imb_dE_fromLab, NULL, NULL ) )
return( -1 );
out->Type = IM_TYPE_B_W;
return( 0 );
return( im__colour_difference( "im_dE_fromLab",
in1, in2, out,
(im_wrapmany_fn) imb_dE_fromLab, NULL, NULL ) );
}

View File

@ -59,8 +59,7 @@
/* Convert a buffer.
*/
void
imb_disp2XYZ( PEL *p, float *q, int n,
struct im_col_display *d, struct im_col_tab_disp *table )
imb_disp2XYZ( PEL *p, float *q, int n, struct im_col_display *d )
{
int x;
@ -71,7 +70,7 @@ imb_disp2XYZ( PEL *p, float *q, int n,
float X, Y, Z;
p += 3;
im_col_rgb2XYZ(d, table, r, g, b, &X, &Y, &Z);
im_col_rgb2XYZ( d, r, g, b, &X, &Y, &Z );
q[0] = X;
q[1] = Y;
@ -83,8 +82,6 @@ imb_disp2XYZ( PEL *p, float *q, int n,
int
im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
struct im_col_tab_disp *table; /* pointer to the lookup tables */
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_UCHAR ||
@ -102,14 +99,10 @@ im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d )
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_XYZ;
/* Prepare the lookup tables
*/
table = im_col_make_tables_RGB( out, d );
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_disp2XYZ, d, table ) )
(im_wrapone_fn) imb_disp2XYZ, d, NULL ) )
return( -1 );
return( 0 );

View File

@ -1,4 +1,5 @@
/* Convert float to Radiance 32bit packed format
*
* 23/3/09
* - from im_rad2float and Radiance sources
*/
@ -180,26 +181,33 @@ float2rad( COLOR *inp, COLR *outbuf, int n )
}
}
/**
* im_float2rad:
* @in: input image
* @out: output image
*
* Convert float to Radiance 32bit packed format.
*
* Returns: 0 on success, -1 on error.
*/
int
im_float2rad( IMAGE *in, IMAGE *out )
{
/* Must be 3-band float.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_float2rad", "%s",
_( "3-band float uncoded only" ) );
return( -1 );
}
IMAGE *t[1];
if( im_cp_desc( out, in ) )
if( im_check_uncoded( "im_float2rad", in ) ||
im_check_bands( "im_float2rad", in, 3 ) ||
im_open_local_array( out, t, 1, "im_float2rad", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
return( -1 );
if( im_cp_desc( out, t[0] ) )
return( -1 );
out->Bands = 4;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = im_bits_of_fmt( out->BandFmt );
out->Coding = IM_CODING_RAD;
if( im_wrapone( in, out,
if( im_wrapone( t[0], out,
(im_wrapone_fn) float2rad, NULL, NULL ) )
return( -1 );

View File

@ -103,7 +103,7 @@ typedef struct {
/* Colour loading and conversion functions.
*/
void im_col_ab2Ch( float a, float b, float *C, float *h );
void im_col_LCh2ab( float L, float C, float h, float *a, float *b );
void im_col_Ch2ab( float C, float h, float *a, float *b );
void im_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b );
void im_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z );
float im_col_pythagoras( float L1, float a1, float b1,

View File

@ -50,6 +50,8 @@ enum im_col_disp_type {
* papers for details on the fields.
*/
struct im_col_display {
/* All private.
*/
/*< private >*/
char *d_name; /* Display name */
enum im_col_disp_type d_type; /* Display type */
@ -77,6 +79,8 @@ struct im_col_display {
* Also holds the luminance to XYZ matrix and the inverse one.
*/
struct im_col_tab_disp {
/* All private.
*/
/*< private >*/
float t_Yr2r[1501]; /* Conversion of Yr to r */
float t_Yg2g[1501]; /* Conversion of Yg to g */
@ -93,21 +97,22 @@ struct im_col_tab_disp {
struct im_col_tab_disp *im_col_make_tables_RGB(
IMAGE *im,
struct im_col_display *d );
struct im_col_tab_disp *im_col_display_get_table( struct im_col_display *d );
int im_col_rgb2XYZ( struct im_col_display *d,
struct im_col_tab_disp *table,
int r, int g, int b,
float *X, float *Y, float *Z );
int im_col_XYZ2rgb(
struct im_col_display *d, struct im_col_tab_disp *table,
struct im_col_display *d,
float X, float Y, float Z,
int *r_ret, int *g_ret, int *b_ret,
int *or_ret );
int im_XYZ2disp( IMAGE *, IMAGE *, struct im_col_display * );
int im_Lab2disp( IMAGE *, IMAGE *, struct im_col_display * );
int im_LabQ2disp( IMAGE *, IMAGE *, struct im_col_display * );
int im_disp2XYZ( IMAGE *, IMAGE *, struct im_col_display * );
int im_disp2Lab( IMAGE *, IMAGE *, struct im_col_display * );
int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d );
int im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *d );
int im_LabQ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d );
int im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d );
int im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d );
/* Colour display values and arrays
&im_col_screen_white, index 0
@ -119,14 +124,16 @@ int im_disp2Lab( IMAGE *, IMAGE *, struct im_col_display * );
&ultra2, index 6
&srgb_profile, index 7
*/
struct im_col_display *im_col_displays( int );
struct im_col_display *im_col_display_name( const char * );
struct im_col_display *im_col_displays( int n );
struct im_col_display *im_col_display_name( const char *name );
void *im_LabQ2disp_build_table( IMAGE *out, struct im_col_display *d );
int im_LabQ2disp_table( IMAGE *in, IMAGE *out, void *table );
int im_dE_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * );
int im_dECMC_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * );
int im_dE_fromdisp( IMAGE *in1, IMAGE *in2, IMAGE *out,
struct im_col_display *d );
int im_dECMC_fromdisp( IMAGE *in1, IMAGE *in2, IMAGE *out,
struct im_col_display *d );
#ifdef __cplusplus
}

View File

@ -163,9 +163,15 @@ typedef int (*im__wrapscan_fn)( void *p, int n, void *seq, void *a, void *b );
int im__wrapscan( IMAGE *in,
im_start_fn start, im__wrapscan_fn scan, im_stop_fn stop,
void *a, void *b );
int im__colour_binary( const char *domain,
IMAGE *in1, IMAGE *in2, int bands, IMAGE *out,
int im__colour_difference( const char *domain,
IMAGE *in1, IMAGE *in2, IMAGE *out,
im_wrapmany_fn buffer_fn, void *a, void *b );
int im__colour_binary( const char *domain,
IMAGE *in1, IMAGE *in2, IMAGE *out,
im_wrapmany_fn buffer_fn, void *a, void *b );
int im__colour_unary( const char *domain,
IMAGE *in, IMAGE *out,
im_wrapone_fn buffer_fn, void *a, void *b );
int im__test_kill( IMAGE *im );
void *im__mmap( int fd, int writeable, size_t length, gint64 offset );