0337c09700
Use GLib's i18n support instead of copying and pasting that logic into its own header. This deprecates the vips/intl.h header in favour of glib/gi18n.h.
253 lines
5.4 KiB
C
253 lines
5.4 KiB
C
/* Lab to XYZ.
|
|
*
|
|
* Modified:
|
|
* 15/11/94 JC
|
|
* - ANSIfied
|
|
* - sets Type of output
|
|
* - better error messages
|
|
* 16/11/94 JC
|
|
* - partialed
|
|
* - in-line conversion
|
|
* 8/2/95 JC
|
|
* - new im_wrapone function
|
|
* 2/11/09
|
|
* - gtkdoc
|
|
* - cleanups
|
|
* 18/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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 USA
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
|
|
|
*/
|
|
|
|
/*
|
|
#define VIPS_DEBUG
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif /*HAVE_CONFIG_H*/
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include <vips/vips.h>
|
|
#include <vips/debug.h>
|
|
|
|
#include "pcolour.h"
|
|
|
|
typedef struct _VipsLab2XYZ {
|
|
VipsColourTransform parent_instance;
|
|
|
|
/* The colour temperature -- default to D65.
|
|
*/
|
|
VipsArea *temp;
|
|
|
|
/* Broken out as xyz.
|
|
*/
|
|
double X0;
|
|
double Y0;
|
|
double Z0;
|
|
|
|
} VipsLab2XYZ;
|
|
|
|
typedef VipsColourTransformClass VipsLab2XYZClass;
|
|
|
|
G_DEFINE_TYPE( VipsLab2XYZ, vips_Lab2XYZ, VIPS_TYPE_COLOUR_TRANSFORM );
|
|
|
|
static void
|
|
vips_col_Lab2XYZ_helper( VipsLab2XYZ *Lab2XYZ,
|
|
float L, float a, float b, float *X, float *Y, float *Z )
|
|
{
|
|
double cby, tmp;
|
|
|
|
if( L < 8.0 ) {
|
|
*Y = (L * Lab2XYZ->Y0) / 903.3;
|
|
cby = 7.787 * (*Y / Lab2XYZ->Y0) + 16.0 / 116.0;
|
|
}
|
|
else {
|
|
cby = (L + 16.0) / 116.0;
|
|
*Y = Lab2XYZ->Y0 * cby * cby * cby;
|
|
}
|
|
|
|
tmp = a / 500.0 + cby;
|
|
if( tmp < 0.2069 )
|
|
*X = Lab2XYZ->X0 * (tmp - 0.13793) / 7.787;
|
|
else
|
|
*X = Lab2XYZ->X0 * tmp * tmp * tmp;
|
|
|
|
tmp = cby - b / 200.0;
|
|
if( tmp < 0.2069 )
|
|
*Z = Lab2XYZ->Z0 * (tmp - 0.13793) / 7.787;
|
|
else
|
|
*Z = Lab2XYZ->Z0 * tmp * tmp * tmp;
|
|
}
|
|
|
|
/* Process a buffer of data.
|
|
*/
|
|
static void
|
|
vips_Lab2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
|
|
{
|
|
VipsLab2XYZ *Lab2XYZ = (VipsLab2XYZ *) colour;
|
|
float * restrict p = (float *) in[0];
|
|
float * restrict q = (float *) out;
|
|
|
|
int x;
|
|
|
|
VIPS_DEBUG_MSG( "vips_Lab2XYZ_line: X0 = %g, Y0 = %g, Z0 = %g\n",
|
|
Lab2XYZ->X0, Lab2XYZ->Y0, Lab2XYZ->Z0 );
|
|
|
|
for( x = 0; x < width; x++ ) {
|
|
float L, a, b;
|
|
float X, Y, Z;
|
|
|
|
L = p[0];
|
|
a = p[1];
|
|
b = p[2];
|
|
p += 3;
|
|
|
|
vips_col_Lab2XYZ_helper( Lab2XYZ, L, a, b, &X, &Y, &Z );
|
|
|
|
/* Write.
|
|
*/
|
|
q[0] = X;
|
|
q[1] = Y;
|
|
q[2] = Z;
|
|
q += 3;
|
|
}
|
|
}
|
|
|
|
static int
|
|
vips_Lab2XYZ_build( VipsObject *object )
|
|
{
|
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
|
VipsLab2XYZ *Lab2XYZ = (VipsLab2XYZ *) object;
|
|
|
|
if( Lab2XYZ->temp ) {
|
|
if( vips_check_vector_length( class->nickname,
|
|
Lab2XYZ->temp->n, 3 ) )
|
|
return( -1 );
|
|
Lab2XYZ->X0 = ((double *) Lab2XYZ->temp->data)[0];
|
|
Lab2XYZ->Y0 = ((double *) Lab2XYZ->temp->data)[1];
|
|
Lab2XYZ->Z0 = ((double *) Lab2XYZ->temp->data)[2];
|
|
}
|
|
|
|
if( VIPS_OBJECT_CLASS( vips_Lab2XYZ_parent_class )->build( object ) )
|
|
return( -1 );
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
static void
|
|
vips_Lab2XYZ_class_init( VipsLab2XYZClass *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 = "Lab2XYZ";
|
|
object_class->description = _( "transform CIELAB to XYZ" );
|
|
object_class->build = vips_Lab2XYZ_build;
|
|
|
|
colour_class->process_line = vips_Lab2XYZ_line;
|
|
|
|
VIPS_ARG_BOXED( class, "temp", 110,
|
|
_( "Temperature" ),
|
|
_( "Color temperature" ),
|
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
|
G_STRUCT_OFFSET( VipsLab2XYZ, temp ),
|
|
VIPS_TYPE_ARRAY_DOUBLE );
|
|
}
|
|
|
|
static void
|
|
vips_Lab2XYZ_init( VipsLab2XYZ *Lab2XYZ )
|
|
{
|
|
VipsColour *colour = VIPS_COLOUR( Lab2XYZ );
|
|
|
|
Lab2XYZ->X0 = VIPS_D65_X0;
|
|
Lab2XYZ->Y0 = VIPS_D65_Y0;
|
|
Lab2XYZ->Z0 = VIPS_D65_Z0;
|
|
|
|
colour->interpretation = VIPS_INTERPRETATION_XYZ;
|
|
}
|
|
|
|
/**
|
|
* vips_Lab2XYZ: (method)
|
|
* @in: input image
|
|
* @out: (out): output image
|
|
* @...: %NULL-terminated list of optional named arguments
|
|
*
|
|
* Optional arguments:
|
|
*
|
|
* * @temp: #VipsArrayDouble, colour temperature
|
|
*
|
|
* Turn Lab to XYZ. The colour temperature defaults to D65, but can be
|
|
* specified with @temp.
|
|
*
|
|
* Returns: 0 on success, -1 on error
|
|
*/
|
|
int
|
|
vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... )
|
|
{
|
|
va_list ap;
|
|
int result;
|
|
|
|
va_start( ap, out );
|
|
result = vips_call_split( "Lab2XYZ", ap, in, out );
|
|
va_end( ap );
|
|
|
|
return( result );
|
|
}
|
|
|
|
/**
|
|
* vips_col_Lab2XYZ:
|
|
* @L: Input CIE Lab value
|
|
* @a: Input CIE Lab value
|
|
* @b: Input CIE Lab value
|
|
* @X: (out): Return CIE XYZ colour
|
|
* @Y: (out): Return CIE XYZ colour
|
|
* @Z: (out): Return CIE XYZ colour
|
|
*
|
|
* Calculate XYZ from Lab, D65.
|
|
*
|
|
* See also: vips_Lab2XYZ().
|
|
*/
|
|
void
|
|
vips_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z )
|
|
{
|
|
VipsLab2XYZ Lab2XYZ;
|
|
|
|
Lab2XYZ.X0 = VIPS_D65_X0;
|
|
Lab2XYZ.Y0 = VIPS_D65_Y0;
|
|
Lab2XYZ.Z0 = VIPS_D65_Z0;
|
|
vips_col_Lab2XYZ_helper( &Lab2XYZ, L, a, b, X, Y, Z );
|
|
}
|