finished colour

This commit is contained in:
John Cupitt 2009-11-02 17:54:42 +00:00
parent d17691ea0c
commit 83fc4b907b
28 changed files with 766 additions and 574 deletions

3
TODO
View File

@ -1,3 +1,6 @@
- poor SMP scaling in benchmark
avg is different? used to 120.134, now 120.151
- more stuff from util.c? too much to do it all now

View File

@ -12,7 +12,7 @@ rm -f swig/vipsCC/*.cxx
rm -f swig/vipsCC/VImage.h
rm -f swig/vipsCC/VImage.py python/vipsCC/VError.py python/vipsCC/VMask.py python/vipsCC/Display.py
rm -f benchmark/temp*
( cd doc ; mkdir poop ; mv reference/libvips-docs.sgml.in poop ; mv reference/Makefile.am poop ; rm -rf reference/* ; mv poop/* reference ; rmdir poop )
( cd doc ; mkdir poop ; mv reference/libvips-docs.sgml.in poop ; mv reference/Makefile.am poop ; mv reference/images poop ; rm -rf reference/* ; mv poop/* reference ; rmdir poop )
gtkdocize --copy --docdir doc/reference --flavour no-tmpl || exit 1

View File

@ -63,7 +63,8 @@ IGNORE_HFILES=merge.h debug.h internal.h intl.h CImg.h im_video_v4l1.h global_ba
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
HTML_IMAGES = \
$(top_srcdir)/doc/reference/images/interconvert.png
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
@ -89,7 +90,8 @@ include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
#EXTRA_DIST +=
EXTRA_DIST += \
images
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types

View File

@ -51,6 +51,8 @@
*
* These operations perform boolean operations, such as bitwise-and, on
* every pixel in an image or pair of images.
* They are useful for combining the results of
* the relational and morphological functions.
* All will work with
* images of any type or any mixture of types of any size and of any number
* of bands.

View File

@ -71,91 +71,6 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/**
* SECTION: colour
* @short_description: colour operators
* @stability: Stable
* @see_also: <link linkend="libvips-arithmetic">arithmetic</link>
* @include: vips/vips.h
*
* These operators let you transform coordinates and images between colour
* spaces, calculate colour differences, and move
* to and from device spaces.
*/
/* Areas under curves for Dxx. 2 degree observer.
*/
/**
* IM_D93_X0:
*
* Areas under curves for D93, 2 degree observer.
*/
/**
* IM_D75_X0:
*
* Areas under curves for D75, 2 degree observer.
*/
/**
* IM_D65_X0:
*
* Areas under curves for D65, 2 degree observer.
*/
/**
* IM_D55_X0:
*
* Areas under curves for D55, 2 degree observer.
*/
/**
* IM_D50_X0:
*
* Areas under curves for D50, 2 degree observer.
*/
/**
* IM_A_X0:
*
* Areas under curves for illuminant A (2856K), 2 degree observer.
*/
/**
* IM_B_X0:
*
* Areas under curves for illuminant B (4874K), 2 degree observer.
*/
/**
* IM_C_X0:
*
* Areas under curves for illuminant C (6774K), 2 degree observer.
*/
/**
* IM_E_X0:
*
* Areas under curves for equal energy illuminant E.
*/
/**
* IM_D3250_X0:
*
* Areas under curves for black body at 3250K, 2 degree observer.
*/
/**
* im_colour_temperature:
* @X0: Area under X
* @Y0: Area under Y
* @Z0: Area under Z
*
* Pass colour temperatures to various operations with one of these.
*/
/* Have the tables been made?
*/
static int made_ucs_tables = 0;
@ -623,6 +538,8 @@ im_col_make_tables_UCS( void )
* @b2:
*
* CMC colour difference from a pair of Lab values.
*
* Returns: CMC(1:1) colour difference
*/
float
im_col_dECMC( float L1, float a1, float b1,

View File

@ -42,6 +42,184 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/**
* SECTION: colour
* @short_description: colour operators
* @stability: Stable
* @see_also: <link linkend="libvips-arithmetic">arithmetic</link>
* @include: vips/vips.h
*
* These operators let you transform coordinates and images between colour
* spaces, calculate colour differences, and move
* to and from device spaces.
*
* Radiance images have four 8-bits bands and store 8 bits of R, G and B and
* another 8 bits of exponent, common to all channels. They are widely used in
* the HDR imaging community.
*
*
* The colour functions can be divided into three main groups. First,
* functions to transform images between the different colour spaces supported
* by VIPS: <emphasis>RGB</emphasis> (also referred to as
* <emphasis>disp</emphasis>), <emphasis>sRGB</emphasis>,
* <emphasis>XYZ</emphasis>, <emphasis>Yxy</emphasis>,
* <emphasis>Lab</emphasis>, <emphasis>LabQ</emphasis>,
* <emphasis>LabS</emphasis>, <emphasis>LCh</emphasis> and
* <emphasis>UCS</emphasis>). Secondly, there are a set of operations for
* calculating colour difference metrics. Finally, VIPS wraps LittleCMS and
* uses it to provide a set of operations for reading and writing images with
* ICC profiles.
*
* This figure shows how the VIPS colour spaces interconvert:
*
* <inlinegraphic fileref="interconvert.png" format="PNG" />
*
* The colour spaces supported by VIPS are:
*
* <itemizedlist>
* <listitem>
* <para>
* <emphasis><code>LabQ</code></emphasis>
*
* This is the principal VIPS colorimetric storage format.
* LabQ images have four 8-bit bands and store 10 bits of L and 11 bits
* of a and b.
*
* You cannot perform calculations on <code>LabQ</code> images (they are
* tagged with IM_CODING_LABQ), though a few operations such as
* im_extract_area() will work directly with them.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>LabS</code></emphasis>
*
* This format represents coordinates in CIELAB space as a
* three-band #IM_BANDFMT_SHORT image, scaled to fit the full range of
* bits. It is the best format for computation, being relatively
* compact, quick, and accurate. Colour values expressed in this way
* are hard to visualise.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>Lab</code></emphasis>
*
* Lab colourspace represents CIELAB colour values with a three-band
* #IM_BANDFMT_FLOAT image. This is the simplest format for general
* work: adding the constant 50 to the L channel, for example, has the
* expected result.
*
* VIPS uses D65 LAB, but you can use other colour temperatures with a
* little effort, see im_XYZ2Lab_temp().
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>XYZ</code></emphasis>
*
* CIE XYZ colour space represented as a three-band #IM_BANDFMT_FLOAT
* image.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>RGB</code></emphasis>
*
* (also refered to as <code>disp</code>+) This is a generic 8-bit RGB
* image. VIPS has a system for going to and from RGB with a simple
* display structure, but it's mostly deprecated. See
* <link linkend="libvips-disp">disp</link>.
*
* Use im_icc_export() and friends as a modern replacement.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>LCh</code></emphasis>
*
* Like <code>Lab</code>, but rectangular <code>ab</code> coordinates
* are replaced with
* polar <code>Ch</code> (Chroma and hue) coordinates.
* Hue angles are expressed in degrees.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis><code>LCh</code></emphasis>
*
* A colour space based on the CMC(1:1) colour difference measurement.
* This is a highly uniform colour space, much better than CIELAB for
* expressing small differences. Conversions to and from
* <code>UCS</code> are extremely slow.
* </para>
* </listitem>
* </itemizedlist>
*/
/* Areas under curves for Dxx. 2 degree observer.
*/
/**
* IM_D93_X0:
*
* Areas under curves for D93, 2 degree observer.
*/
/**
* IM_D75_X0:
*
* Areas under curves for D75, 2 degree observer.
*/
/**
* IM_D65_X0:
*
* Areas under curves for D65, 2 degree observer.
*/
/**
* IM_D55_X0:
*
* Areas under curves for D55, 2 degree observer.
*/
/**
* IM_D50_X0:
*
* Areas under curves for D50, 2 degree observer.
*/
/**
* IM_A_X0:
*
* Areas under curves for illuminant A (2856K), 2 degree observer.
*/
/**
* IM_B_X0:
*
* Areas under curves for illuminant B (4874K), 2 degree observer.
*/
/**
* IM_C_X0:
*
* Areas under curves for illuminant C (6774K), 2 degree observer.
*/
/**
* IM_E_X0:
*
* Areas under curves for equal energy illuminant E.
*/
/**
* IM_D3250_X0:
*
* Areas under curves for black body at 3250K, 2 degree observer.
*/
/* One image in, one out.
*/
static im_arg_desc one_in_one_out[] = {
@ -347,34 +525,6 @@ static im_function icc_export_depth_desc = {
icc_export_depth_args /* Arg list */
};
static int
icc_export_vec( im_object *argv )
{
int intent = *((int *) argv[3]);
return( im_icc_export( argv[0], argv[1],
argv[2], intent ) );
}
static im_arg_desc icc_export_args[] = {
IM_INPUT_IMAGE( "in" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_STRING( "output_profile" ),
IM_INPUT_INT( "intent" )
};
/* Description of im_icc_export.
*/
static im_function icc_export_desc = {
"im_icc_export", /* Name */
"convert a float LAB to an 8-bit device image with an ICC profile",
/* Description */
IM_FN_PIO, /* Flags */
icc_export_vec, /* Dispatch function */
IM_NUMBER( icc_export_args ), /* Size of arg list */
icc_export_args /* Arg list */
};
static int
icc_ac2rc_vec( im_object *argv )
{
@ -1032,7 +1182,6 @@ static im_function *colour_list[] = {
&disp2XYZ_desc,
&float2rad_desc,
&icc_ac2rc_desc,
&icc_export_desc,
&icc_export_depth_desc,
&icc_import_desc,
&icc_import_embedded_desc,

View File

@ -1,12 +1,5 @@
/* @(#) Turn LCh to Lab.
* @(#)
* @(#) Usage:
* @(#) im_LCh2Lab( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* im_LCh2Lab
*
* 15/11/94 JC
* - error messages added
* - memory leak fixed
@ -14,6 +7,8 @@
* - uses im_wrap_oneonebuf() now
* 8/2/95 JC
* - im_wrap v2
* 2/11/09
* - gtkdoc
*/
/*
@ -51,6 +46,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -81,29 +77,18 @@ imb_LCh2Lab( float *p, float *q, int n )
}
}
/**
* im_LCh2Lab:
* @in: input image
* @out: output image
*
* Turn LCh to Lab.
*
* Returns: 0 on success, -1 on error.
*/
int
im_LCh2Lab( IMAGE *in, IMAGE *out )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_LCh2Lab", "%s",
_( "3-band float uncoded input only" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LCh2Lab, NULL, NULL ) )
return( -1 );
return( 0 );
return( im__colour_unary( "im_LCh2Lab", in, out, IM_TYPE_LAB,
(im_wrapone_fn) imb_LCh2Lab, NULL, NULL ) );
}

View File

@ -1,13 +1,8 @@
/* @(#) Turn LCh to UCS.
* @(#)
* @(#) Usage:
* @(#) im_LCh2UCS( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* im_LCh2UCS
*
* Modified:
* 2/11/09
* - gtkdoc
*/
/*
@ -45,6 +40,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -72,29 +68,18 @@ imb_LCh2UCS( float *p, float *q, int n )
}
}
/**
* 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 )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_LCh2UCS", "%s",
_( "3-band uncoded float input only" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_UCS;
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LCh2UCS, NULL, NULL ) )
return( -1 );
return( 0 );
{
return( im__colour_unary( "im_LCh2UCS", in, out, IM_TYPE_UCS,
(im_wrapone_fn) imb_LCh2UCS, NULL, NULL ) );
}

View File

@ -1,4 +1,8 @@
/* Turn Lab to LCh
*
* 2/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -69,7 +73,7 @@ imb_Lab2LCh( float *p, float *q, int n )
int
im__colour_unary( const char *domain,
IMAGE *in, IMAGE *out,
IMAGE *in, IMAGE *out, VipsType type,
im_wrapone_fn buffer_fn, void *a, void *b )
{
IMAGE *t[1];
@ -82,6 +86,7 @@ im__colour_unary( const char *domain,
if( im_cp_desc( out, t[0] ) )
return( -1 );
out->Type = type;
if( im_wrapone( t[0], out,
(im_wrapone_fn) buffer_fn, a, b ) )
@ -102,11 +107,6 @@ im__colour_unary( const char *domain,
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 );
return( im__colour_unary( "im_Lab2LCh", in, out, IM_TYPE_LCH,
(im_wrapone_fn) imb_Lab2LCh, NULL, NULL ) );
}

View File

@ -127,6 +127,17 @@ imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n )
}
}
/**
* im_Lab2LabQ:
* @in: input image
* @out: output image
*
* Convert a Lab three-band float image to LabQ (#IM_CODING_LABQ).
*
* See also: im_LabQ2Lab().
*
* Returns: 0 on success, -1 on error.
*/
int
im_Lab2LabQ( IMAGE *in, IMAGE *out )
{

View File

@ -1,12 +1,5 @@
/* @(#) Turn Lab to XYZ colourspace.
* @(#)
* @(#) Usage:
* @(#) im_Lab2XYZ( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* Lab to XYZ.
*
* Modified:
* 15/11/94 JC
* - ANSIfied
@ -17,6 +10,9 @@
* - in-line conversion
* 8/2/95 JC
* - new im_wrapone function
* 2/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -54,6 +50,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -106,40 +103,42 @@ imb_Lab2XYZ( float *p, float *q, int n, im_colour_temperature *temp )
}
}
/**
* im_Lab2XYZ_temp:
* @in: input image
* @out: output image
* @X0: colour temperature
* @Y0: colour temperature
* @Z0: colour temperature
*
* Turn Lab to XYZ. @X0, @y0, @Z0 give the Lab colour temperature.
*
* Returns: 0 on success, -1 on error.
*/
int
im_Lab2XYZ_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
{
im_colour_temperature *temp;
/* Check input image.
*/
if( !(temp = IM_NEW( out, im_colour_temperature )) )
return( -1 );
if( in->Bands != 3 ||
in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_Lab2XYZ", "%s", _( "not 3-band uncoded float" ) );
return( -1 );
}
/* Prepare the output image.
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_XYZ;
/* Process!
*/
temp->X0 = X0;
temp->Y0 = Y0;
temp->Z0 = Z0;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Lab2XYZ, temp, NULL ) )
return( -1 );
return( 0 );
return( im__colour_unary( "im_Lab2XYZ_temp", in, out, IM_TYPE_XYZ,
(im_wrapone_fn) imb_Lab2XYZ, temp, NULL ) );
}
/**
* im_Lab2XYZ:
* @in: input image
* @out: output image
*
* Turn D65 Lab to XYZ.
*
* Returns: 0 on success, -1 on error.
*/
int
im_Lab2XYZ( IMAGE *in, IMAGE *out )
{

View File

@ -1,7 +1,8 @@
/* @(#) LabQ2Lab convert Lab 32bit packed format to float Lab
@(#) uses imb_LabQ2Lab
Copyright Kirk Martinez 2/5/1993
Modified: 16/6/93
/* im_LabQ2Lab
*
* Copyright Kirk Martinez 2/5/1993
*
* Modified: 16/6/93
* 7/6/93 JC
* - adapted for partial v2
* 16/11/94 JC
@ -13,6 +14,8 @@ Modified: 16/6/93
* - small tidies and speed-ups
* 4/9/97 JC
* - L* = 100.0 now handled correctly
* 2/11/09
* - gtkdoc
*/
/*
@ -100,32 +103,37 @@ imb_LabQ2Lab( PEL *inp, float *outbuf, int n )
}
}
/* unpack a Lab32 ie 10,11,11 Lab image into float image
this is a wrapper around the buffer processing function
(C) K.Martinez 2/5/93
*/
/**
* im_LabQ2Lab:
* @in: input image
* @out: output image
*
* Unpack a LabQ (#IM_CODING_LABQ) image to a three-band float image.
*
* See also: im_LabQ2Lab(), im_LabQ2LabS(), im_rad2float().
*
* Returns: 0 on success, -1 on error.
*/
int
im_LabQ2Lab( IMAGE *labim, IMAGE *outim )
im_LabQ2Lab( IMAGE *in, IMAGE *out )
{
/* check for coded Lab type
*/
if( labim->Coding != IM_CODING_LABQ ) {
im_error( "im_LabQ2Lab", "%s", _( "not a packed Lab image" ) );
if( in->Coding != IM_CODING_LABQ ) {
im_error( "im_LabQ2Lab", "%s", _( "not a LabQ image" ) );
return( -1 );
}
/* set up output image
*/
if( im_cp_desc( outim, labim ) )
if( im_cp_desc( out, in ) )
return( -1 );
outim->Bands = 3;
outim->Type = IM_TYPE_LAB;
outim->BandFmt = IM_BANDFMT_FLOAT;
outim->Bbits = 32;
outim->Coding = IM_CODING_NONE;
out->Bands = 3;
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Coding = IM_CODING_NONE;
if( im_wrapone( labim, outim,
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LabQ2Lab, NULL, NULL ) )
return( -1 );

View File

@ -1,9 +1,4 @@
/* @(#) im_LabQ2LabS() - convert IM_CODING_LABQ format to three band signed short.
* @(#) Justify to get msb in bit 15.
* @(#)
* @(#) int im_LabQ2LabS( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
/* im_LabQ2LabS
*
* 17/11/93 JC
* - adapted from im_LabQ2Lab()
@ -11,6 +6,8 @@
* - uses new im_wrap_oneonebuf() fn
* 9/2/95 JC
* - new im_wrapone function
* 2/11/09
* - gtkdoc
*/
/*
@ -90,17 +87,23 @@ imb_LabQ2LabS( unsigned char *in, signed short *out, int n )
}
}
/* unpack a Lab32 ie 10,11,11 Lab image into signed short image
this is a wrapper around the buffer processing function
(C) K.Martinez 2/5/93
*/
/**
* im_LabQ2LabS:
* @in: input image
* @out: output image
*
* Unpack a LabQ (#IM_CODING_LABQ) image to a three-band signed short image.
*
* See also: im_LabS2LabQ(), im_LabQ2Lab(), im_rad2float().
*
* Returns: 0 on success, -1 on error.
*/
int
im_LabQ2LabS( IMAGE *labim, IMAGE *outim )
im_LabQ2LabS( IMAGE *in, IMAGE *out )
{
/* check for coded Lab type
*/
if( labim->Coding != IM_CODING_LABQ ) {
if( in->Coding != IM_CODING_LABQ ) {
im_error( "im_LabQ2LabS", "%s",
_( "not a packed Lab image" ) );
return( -1 );
@ -108,17 +111,16 @@ im_LabQ2LabS( IMAGE *labim, IMAGE *outim )
/* set up output image
*/
if( im_cp_desc( outim, labim ) )
if( im_cp_desc( out, in ) )
return( -1 );
outim->Bands = 3;
outim->Type = IM_TYPE_LABS;
outim->BandFmt = IM_BANDFMT_SHORT;
outim->Bbits = IM_BBITS_SHORT;
outim->Coding = IM_CODING_NONE;
out->Bands = 3;
out->Type = IM_TYPE_LABS;
out->BandFmt = IM_BANDFMT_SHORT;
out->Coding = IM_CODING_NONE;
/* Produce output.
*/
if( im_wrapone( labim, outim,
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LabQ2LabS, NULL, NULL ) )
return( -1 );

View File

@ -1,11 +1,9 @@
/* @(#) im_LabS2Lab() - convert short LAB format to Lab.
* @(#)
* @(#) int im_LabS2Lab( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
/* im_LabS2Lab()
*
* 12/12/02 JC
* - adapted from im_LabS2LabQ()
* 2/11/09
* - gtkdoc, cleanup
*/
/*
@ -66,29 +64,29 @@ imb_LabS2Lab( signed short *in, float *out, int n )
}
}
/**
* im_LabS2Lab:
* @in: input image
* @out: output image
*
* Convert a LabS three-band signed short image to a three-band float image.
*
* See also: im_Lab2LabS().
*
* Returns: 0 on success, -1 on error.
*/
int
im_LabS2Lab( IMAGE *in, IMAGE *out )
{
/* Check type.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_LabS2Lab", "%s",
_( "not an uncoded image" ) );
if( im_check_uncoded( "im_LabS2Lab", in ) ||
im_check_bands( "im_LabS2Lab", in, 3 ) ||
im_check_format( "im_LabS2Lab", in, IM_BANDFMT_SHORT ) )
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_SHORT || in->Bands != 3 ) {
im_error( "im_LabS2Lab", "%s",
_( "not a 3-band signed short image" ) );
return( -1 );
}
/* Set up output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = IM_BBITS_FLOAT;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_LabS2Lab, NULL, NULL ) )

View File

@ -1,8 +1,4 @@
/* @(#) im_LabS2LabQ() - convert short LAB format to IM_CODING_LABQ.
* @(#)
* @(#) int im_LabS2LabQ( IMAGE *in, IMAGE *out )
* @(#)
* @(#)
/* im_LabS2LabQ()
*
* 17/11/93 JC
* - adapted from im_LabQ2LabS()
@ -15,6 +11,8 @@
* - somewhat slower ...
* 21/12/99 JC
* - a/b ==0 rounding was broken
* 2/11/09
* - gtkdoc, cleanup
*/
/*
@ -119,21 +117,27 @@ imb_LabS2LabQ( signed short *in, unsigned char *out, int n )
}
}
/**
* im_LabS2LabQ:
* @in: input image
* @out: output image
*
* Convert a LabS three-band signed short image to LabQ
*
* See also: im_LabQ2LabS().
*
* Returns: 0 on success, -1 on error.
*/
int
im_LabS2LabQ( IMAGE *in, IMAGE *out )
{
/* Check type.
*/
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_LabS2LabQ", "%s",
_( "not an uncoded image" ) );
IMAGE *t[1];
if( im_check_uncoded( "im_LabS2LabQ", in ) ||
im_check_bands( "im_LabS2LabQ", in, 3 ) ||
im_open_local_array( out, t, 1, "im_LabS2LabQ", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_SHORT ) )
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_SHORT || in->Bands != 3 ) {
im_error( "im_LabS2LabQ", "%s",
_( "not a 3-band signed short image" ) );
return( -1 );
}
/* Set up output image
*/
@ -142,7 +146,6 @@ im_LabS2LabQ( IMAGE *in, IMAGE *out )
out->Bands = 4;
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = 8;
out->Coding = IM_CODING_LABQ;
if( im_wrapone( in, out,

View File

@ -1,17 +1,12 @@
/* @(#) Turn UCS to LCh
* @(#)
* @(#) Usage:
* @(#) im_UCS2LCh( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 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
*/
/*
@ -49,6 +44,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -81,30 +77,18 @@ imb_UCS2LCh( float *p, float *q, int n )
}
}
/**
* 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 )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_UCS2LCh", "%s",
_( "3-band float uncoded input only" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in) )
return( -1 );
out->Type = IM_TYPE_LCH;
/* Do the processing.
*/
im_col_make_tables_UCS();
if( im_wrapone( in, out,
(im_wrapone_fn) imb_UCS2LCh, NULL, NULL ) )
return( -1 );
return( 0 );
return( im__colour_unary( "im_UCS2LCh", in, out, IM_TYPE_UCS,
(im_wrapone_fn) imb_UCS2LCh, NULL, NULL ) );
}

View File

@ -1,12 +1,5 @@
/* @(#) Turn XYZ to Lab colourspace.
* @(#)
* @(#) Usage:
* @(#) im_XYZ2Lab( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* Turn XYZ to Lab colourspace.
*
* Modifed:
* 16/11/94 JC
* - uses im_wrapone()
@ -20,6 +13,8 @@
* - use a large LUT instead, about 5x faster
* 23/11/06
* - ahem, build the LUT outside the eval thread
* 2/11/09
* - gtkdoc
*/
/*
@ -147,42 +142,43 @@ imb_XYZ2Lab( float *p, float *q, int n, im_colour_temperature *temp )
}
}
/**
* im_XYZ2Lab_temp:
* @in: input image
* @out: output image
* @X0: colour temperature
* @Y0: colour temperature
* @Z0: colour temperature
*
* Turn XYZ to Lab. @X0, @y0, @Z0 give the Lab colour temperature.
*
* Returns: 0 on success, -1 on error.
*/
int
im_XYZ2Lab_temp( IMAGE *in, IMAGE *out,
double X0, double Y0, double Z0 )
im_XYZ2Lab_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
{
im_colour_temperature *temp;
/* Check input image.
*/
if( !(temp = IM_NEW( out, im_colour_temperature )) )
return( -1 );
if( in->Bands != 3 ||
in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_XYZ2Lab", "%s", _( "not 3-band uncoded float" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in) )
return( -1 );
out->Type = IM_TYPE_LAB;
/* Do the processing.
*/
imb_XYZ2Lab_tables();
temp->X0 = X0;
temp->Y0 = Y0;
temp->Z0 = Z0;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2Lab, temp, NULL ) )
return( -1 );
imb_XYZ2Lab_tables();
return( 0 );
return( im__colour_unary( "im_XYZ2Lab", in, out, IM_TYPE_LAB,
(im_wrapone_fn) imb_XYZ2Lab, temp, NULL ) );
}
/**
* im_XYZ2Lab:
* @in: input image
* @out: output image
*
* Turn XYZ to D65 Lab.
*
* Returns: 0 on success, -1 on error.
*/
int
im_XYZ2Lab( IMAGE *in, IMAGE *out )
{

View File

@ -1,15 +1,11 @@
/* @(#) Turn XYZ to Yxy colourspace.
* @(#)
* @(#) Usage:
* @(#) im_XYZ2Yxy( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* Turn XYZ to Yxy colourspace.
*
* Modified:
* 29/5/02 JC
* - from lab2xyz
* 2/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -47,6 +43,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -79,24 +76,19 @@ imb_XYZ2Yxy( float *p, float *q, int n )
}
}
/**
* im_XYZ2Yxy:
* @in: input image
* @out: output image
*
* Turn XYZ to Yxy.
*
* Returns: 0 on success, -1 on error.
*/
int
im_XYZ2Yxy( IMAGE *in, IMAGE *out )
{
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_XYZ2Yxy", "%s",
_( "3-band uncoded float input only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_YXY;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2Yxy, NULL, NULL ) )
return( -1 );
return( 0 );
return( im__colour_unary( "im_XYZ2Yxy", in, out, IM_TYPE_YXY,
(im_wrapone_fn) imb_XYZ2Yxy, NULL, NULL ) );
}

View File

@ -1,15 +1,11 @@
/* @(#) Turn Yxy to XYZ colourspace.
* @(#)
* @(#) Usage:
* @(#) im_Yxy2XYZ( imagein, imageout )
* @(#) IMAGE *imagein, *imageout;
* @(#)
* @(#) Float in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
/* Turn Yxy to XYZ colourspace.
*
* Modified:
* 29/5/02 JC
* - from lab2xyz
* 2/11/09
* - gtkdoc
* - cleanups
*/
/*
@ -47,6 +43,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -80,24 +77,19 @@ imb_Yxy2XYZ( float *p, float *q, int n )
}
}
/**
* im_Yxy2XYZ:
* @in: input image
* @out: output image
*
* Turn Yxy to XYZ.
*
* Returns: 0 on success, -1 on error.
*/
int
im_Yxy2XYZ( IMAGE *in, IMAGE *out )
{
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_Yxy2XYZ", "%s",
_( "3-band uncoded float input only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_XYZ;
if( im_wrapone( in, out,
(im_wrapone_fn) imb_Yxy2XYZ, NULL, NULL ) )
return( -1 );
return( 0 );
{
return( im__colour_unary( "im_Yxy2XYZ", in, out, IM_TYPE_XYZ,
(im_wrapone_fn) imb_Yxy2XYZ, NULL, NULL ) );
}

View File

@ -2,6 +2,8 @@
*
* 23/3/09
* - from im_rad2float and Radiance sources
* 2/11/09
* - gtkdoc
*/
/*
@ -186,7 +188,9 @@ float2rad( COLOR *inp, COLR *outbuf, int n )
* @in: input image
* @out: output image
*
* Convert float to Radiance 32bit packed format.
* Convert a three-band float image to Radiance 32-bit packed format.
*
* See also: im_rad2float(), #VipsFormatRad, im_LabQ2Lab().
*
* Returns: 0 on success, -1 on error.
*/

View File

@ -1,5 +1,4 @@
/* @(#) Transform images with little cms
* @(#)
/* Transform images with little cms
*
* 26/4/02 JC
* 26/8/05
@ -11,6 +10,11 @@
* - set RGB16 on 16-bit RGB export
* 6/4/09
* - catch lcms error messages
* 2/11/09
* - gtkdoc
* - small cleanups
* - call attach_profile() before im_wrapone() so the profile will get
* written if we are wrinting to a file
*/
/*
@ -135,12 +139,24 @@ im_icc_ac2rc( IMAGE *in, IMAGE *out, const char *profile_filename )
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/**
* VipsIntent:
* @IM_INTENT_PERCEPTUAL:
* @IM_INTENT_RELATIVE_COLORIMETRIC:
* @IM_INTENT_SATURATION:
* @IM_INTENT_ABSOLUTE_COLORIMETRIC:
*
* The rendering intent. #IM_INTENT_ABSOLUTE_COLORIMETRIC is best for
* scientific work, #IM_INTENT_RELATIVE_COLORIMETRIC is usually best for
* accurate communication with other imaging libraries.
*/
/* Call lcms with up to this many pixels at once.
*/
#define PIXEL_BUFFER_SIZE (10000)
static const char *
decode_intent( int intent )
decode_intent( VipsIntent intent )
{
switch( intent ) {
case IM_INTENT_PERCEPTUAL: return( "PERCEPTUAL" );
@ -151,6 +167,14 @@ decode_intent( int intent )
}
}
/**
* im_icc_present:
*
* VIPS can optionally be built without the ICC library. Use this function to
* test for its availability.
*
* Returns: non-zero if the ICC library is present.
*/
int
im_icc_present( void )
{
@ -164,7 +188,7 @@ typedef struct {
IMAGE *out;
const char *input_profile_filename;
const char *output_profile_filename;
int intent;
VipsIntent intent;
cmsHPROFILE in_profile;
cmsHPROFILE out_profile;
@ -200,7 +224,7 @@ icc_destroy( Icc *icc )
}
static Icc *
icc_new( IMAGE *in, IMAGE *out, int intent )
icc_new( IMAGE *in, IMAGE *out, VipsIntent intent )
{
Icc *icc;
@ -233,7 +257,7 @@ static Icc *
icc_new_file( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent )
VipsIntent intent )
{
Icc *icc;
@ -277,7 +301,7 @@ icc_new_file( IMAGE *in, IMAGE *out,
static Icc *
icc_new_mem( IMAGE *in, IMAGE *out,
void *data, int data_length,
int intent )
VipsIntent intent )
{
Icc *icc;
@ -370,20 +394,37 @@ attach_profile( IMAGE *im, const char *filename )
return( 0 );
}
/**
* im_icc_transform:
* @in: input image
* @out: output image
* @input_profile_filename: get the input profile from here
* @output_profile_filename: get the output profile from here
* @intent: transform with this intent
*
* Transform an image with the ICC library. The input image is moved to
* profile-connection space with the input profile and then to the output
* space with the output profile.
*
* Use im_icc_import() and im_icc_export() to do either the first or second
* half of this operation in isolation.
*
* See also: im_icc_import(), im_icc_export().
*
* Returns: 0 on success, -1 on error.
*/
int
im_icc_transform( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent )
VipsIntent intent )
{
Icc *icc;
DWORD in_icc_format;
DWORD out_icc_format;
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_transform", "%s", _( "uncoded input only" ) );
if( im_check_uncoded( "im_icc_transform", in ) )
return( -1 );
}
if( !(icc = icc_new_file( in, out,
input_profile_filename, output_profile_filename, intent )) )
@ -429,8 +470,9 @@ im_icc_transform( IMAGE *in, IMAGE *out,
break;
default:
im_error( "im_icc_transform", _( "unimplemented input colour "
"space 0x%x" ), cmsGetColorSpace( icc->in_profile ) );
im_error( "im_icc_transform",
_( "unimplemented input colour space 0x%x" ),
cmsGetColorSpace( icc->in_profile ) );
return( -1 );
}
@ -443,7 +485,6 @@ im_icc_transform( IMAGE *in, IMAGE *out,
case icSigCmykData:
out->Type = IM_TYPE_CMYK;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = IM_BBITS_BYTE;
out->Bands = 4;
out_icc_format = TYPE_CMYK_8;
break;
@ -451,14 +492,14 @@ im_icc_transform( IMAGE *in, IMAGE *out,
case icSigRgbData:
out->Type = IM_TYPE_RGB;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = IM_BBITS_BYTE;
out->Bands = 3;
out_icc_format = TYPE_RGB_8;
break;
default:
im_error( "im_icc_transform", _( "unimplemented output colour "
"space 0x%x" ), cmsGetColorSpace( icc->out_profile ) );
im_error( "im_icc_transform",
_( "unimplemented output colour space 0x%x" ),
cmsGetColorSpace( icc->out_profile ) );
return( -1 );
}
@ -481,15 +522,15 @@ im_icc_transform( IMAGE *in, IMAGE *out,
icc->out_profile, out_icc_format, intent, 0 )) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
/* Process!
*/
if( im_wrapone( in, out,
(im_wrapone_fn) transform_buf, icc, NULL ) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
return( 0 );
}
@ -519,10 +560,8 @@ icc_import( IMAGE *in, IMAGE *out, Icc *icc )
{
DWORD icc_format;
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_import", "%s", _( "uncoded input only" ) );
if( im_check_uncoded( "im_icc_import", in ) )
return( -1 );
}
if( !cmsIsIntentSupported( icc->in_profile,
icc->intent, LCMS_USED_AS_INPUT ) )
@ -538,7 +577,6 @@ icc_import( IMAGE *in, IMAGE *out, Icc *icc )
return( -1 );
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = IM_BBITS_FLOAT;
out->Bands = 3;
switch( cmsGetColorSpace( icc->in_profile ) ) {
@ -595,9 +633,23 @@ icc_import( IMAGE *in, IMAGE *out, Icc *icc )
return( 0 );
}
/**
* im_icc_import:
* @in: input image
* @out: output image
* @input_profile_filename: get the input profile from here
* @intent: transform with this intent
*
* Import an image with the ICC library. The input image in device space
* is moved to D65 LAB with the input profile.
*
* See also: im_icc_transform(), im_icc_import_embedded().
*
* Returns: 0 on success, -1 on error.
*/
int
im_icc_import( IMAGE *in, IMAGE *out,
const char *input_profile_filename, int intent )
const char *input_profile_filename, VipsIntent intent )
{
Icc *icc;
@ -609,8 +661,22 @@ im_icc_import( IMAGE *in, IMAGE *out,
return( 0 );
}
/**
* im_icc_import_embedded:
* @in: input image
* @out: output image
* @intent: transform with this intent
*
* Import an image with the ICC library. The input image in device space
* is moved to D65 LAB with the input profile attached to the image under the
* name #IM_META_ICC_NAME.
*
* See also: im_icc_transform(), im_icc_import().
*
* Returns: 0 on success, -1 on error.
*/
int
im_icc_import_embedded( IMAGE *in, IMAGE *out, int intent )
im_icc_import_embedded( IMAGE *in, IMAGE *out, VipsIntent intent )
{
Icc *icc;
void *data;
@ -651,9 +717,25 @@ export_buf( float *in, PEL *out, int n, Icc *icc )
}
}
/**
* im_icc_export_depth:
* @in: input image
* @out: output image
* @depth: depth to export at
* @output_profile_filename: use this profile
* @intent: transform with this intent
*
* Export an image with the ICC library. The input image in
* D65 LAB is transformed to device space using the supplied profile.
* @depth can be 8 or 16, for 8 or 16-bit image export.
*
* See also: im_icc_transform(), im_icc_import().
*
* Returns: 0 on success, -1 on error.
*/
int
im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
const char *output_profile_filename, int intent )
const char *output_profile_filename, VipsIntent intent )
{
Icc *icc;
DWORD icc_format;
@ -682,12 +764,10 @@ im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_icc_export",
"%s", _( "3-band uncoded Lab float only" ) );
return( -1 );
}
if( im_check_uncoded( "im_icc_export", in ) ||
im_check_bands( "im_icc_export", in, 3 ) ||
im_check_format( "im_icc_export", in, IM_BANDFMT_FLOAT ) )
return( -1 );
if( depth != 8 && depth != 16 ) {
im_error( "im_icc_export", "%s", _( "unsupported bit depth" ) );
@ -717,7 +797,6 @@ im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
out->Type = IM_TYPE_CMYK;
out->BandFmt = depth == 8 ?
IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT;
out->Bbits = depth == 8 ? IM_BBITS_BYTE : IM_BBITS_SHORT;
out->Bands = 4;
icc_format = depth == 8 ? TYPE_CMYK_8 : TYPE_CMYK_16;
break;
@ -727,7 +806,6 @@ im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
IM_TYPE_RGB : IM_TYPE_RGB16;
out->BandFmt = depth == 8 ?
IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT;
out->Bbits = depth == 8 ? IM_BBITS_BYTE : IM_BBITS_SHORT;
out->Bands = 3;
icc_format = depth == 8 ? TYPE_RGB_8 : TYPE_RGB_16;
break;
@ -742,25 +820,30 @@ im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
icc->out_profile, icc_format, intent, 0 )) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
/* Process!
*/
if( im_wrapone( in, out, (im_wrapone_fn) export_buf, icc, NULL ) )
return( -1 );
if( attach_profile( out, output_profile_filename ) )
return( -1 );
return( 0 );
}
int
im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, int intent )
{
return( im_icc_export_depth( in, out,
8, output_profile_filename, intent ) );
}
/**
* im_icc_ac2rc:
* @in: input image
* @out: output image
* @profile_filename: use this profile
*
* Transform an image from absolute to relative colorimetry using the
* MediaWhitePoint stored in the ICC profile.
*
* See also: im_icc_transform(), im_icc_import().
*
* Returns: 0 on success, -1 on error.
*/
int
im_icc_ac2rc( IMAGE *in, IMAGE *out, const char *profile_filename )
{

View File

@ -1,28 +1,10 @@
/* Morph a lab image ... adjust:
*
* - cast
* Pass in a MASK containing CIELAB readings for a neutral greyscale ...
* eg.
/* Morph a lab image.
*
* 3 4
* 14.23 4.8 -3.95
* 18.74 2.76 -2.62
* 23.46 1.4 -1.95
* 27.53 1.76 -2.01
*
* interpolation from this makes cast corrector ... interpolate top and
* tail towards [0,0,0] and [100,0,0] ... can be in any order (ie. need
* not be sorted on L*)
*
* - L*
* Pass in scale and offset for L* ... L*' = (L* + offset) * scale
*
* - saturation
* scale a and b by these amounts ... eg. 1.5 increases saturation ...
* useful for some gammut mapping
*
* Find the top two by generating and printing a greyscale ... find the bottom
* by printing a Macbeth and looking at a/b spread
* 8/3/01
* - added
* 2/11/09
* - cleanups
* - gtkdoc
*/
/*
@ -62,6 +44,7 @@
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -74,7 +57,6 @@ typedef struct {
double a_offset[101], b_offset[101];
double a_scale, b_scale;
} Params;
static int
@ -161,48 +143,116 @@ morph_init( Params *parm,
return( 0 );
}
#define loop( TYPE ) \
{ \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < width; x++ ) { \
double L = p[0]; \
double a = p[1]; \
double b = p[2]; \
\
L = IM_CLIP( 0, L, 100 ); \
a -= parm->a_offset[(int) L]; \
b -= parm->b_offset[(int) L]; \
\
L = (L + parm->L_offset) * parm->L_scale; \
L = IM_CLIP( 0, L, 100 ); \
\
a *= parm->a_scale; \
b *= parm->b_scale; \
\
q[0] = L; \
q[1] = a; \
q[2] = b; \
\
p += 3; \
q += 3; \
} \
}
static void
morph_buffer( float *in, float *out, int width, Params *parm )
{
int x;
switch( parm->in->BandFmt ) {
case IM_BANDFMT_FLOAT: loop( float ); break;
case IM_BANDFMT_DOUBLE: loop( double ); break;
default: assert( 0 );
}
for( x = 0; x < width; x++ ) {
double L = in[0];
double a = in[1];
double b = in[2];
L = IM_CLIP( 0, L, 100 );
a -= parm->a_offset[(int) L];
b -= parm->b_offset[(int) L];
L = (L + parm->L_offset) * parm->L_scale;
L = IM_CLIP( 0, L, 100 );
a *= parm->a_scale;
b *= parm->b_scale;
out[0] = L;
out[1] = a;
out[2] = b;
in += 3;
out += 3;
}
}
/* Morph an image.
/**
* im_lab_morph:
* @in: input image
* @out: output image
* @mask: cast correction table
* @L_offset: L adjustment
* @L_scale: L adjustment
* @a_scale: a scale
* @b_scale: b scale
*
* Morph an image in CIELAB colour space. Useful for certain types of gamut
* mapping, or correction of greyscales on some printers.
*
* We perform three adjustments:
*
* <itemizedlist>
* <listitem>
* <para>
* <emphasis>cast</emphasis>
*
* Pass in @mask containing CIELAB readings for a neutral greyscale. For
* example:
*
* <tgroup cols='3' align='left' colsep='1' rowsep='1'>
* <tbody>
* <row>
* <entry>3</entry>
* <entry>4</entry>
* </row>
* <row>
* <entry>14.23</entry>
* <entry>4.8</entry>
* <entry>-3.95</entry>
* </row>
* <row>
* <entry>18.74</entry>
* <entry>2.76</entry>
* <entry>-2.62</entry>
* </row>
* <row>
* <entry>23.46</entry>
* <entry>1.4</entry>
* <entry>-1.95</entry>
* </row>
* <row>
* <entry>27.53</entry>
* <entry>1.76</entry>
* <entry>-2.01</entry>
* </row>
* </tbody>
* </tgroup>
*
* Interpolation from this makes cast corrector. The top and tail are
* interpolated towards [0, 0, 0] and [100, 0, 0], intermediate values are
* interpolated along straight lines fitted between the specified points.
* Rows may be in any order (ie. they need not be sorted on L*).
*
* Each pixel is displaced in a/b by the amount specified for that L in the
* table.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>L*</emphasis>
*
* Pass in scale and offset for L. L' = (L + offset) * scale.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>saturation</emphasis>
*
* scale a and b by these amounts, eg. 1.5 increases saturation.
* </para>
* </listitem>
* </itemizedlist>
*
* Find the top two by generating and printing a greyscale. Find the bottom
* by printing a Macbeth and looking at a/b spread
*
* Returns: 0 on success, -1 on error.
*/
int
im_lab_morph( IMAGE *in, IMAGE *out,
@ -215,47 +265,23 @@ im_lab_morph( IMAGE *in, IMAGE *out,
/* Recurse for coded images.
*/
if( in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "im_lab_morph:1", "p" );
IMAGE *t2 = im_open_local( out, "im_lab_morph:2", "p" );
IMAGE *t[2];
if( !t1 || !t2 ||
im_LabQ2Lab( in, t1 ) ||
im_lab_morph( t1, t2,
if( im_open_local_array( out, t, 2, "im_lab_morph", "p" ) ||
im_LabQ2Lab( in, t[0] ) ||
im_lab_morph( t[0], t[1],
mask, L_offset, L_scale, a_scale, b_scale ) ||
im_Lab2LabQ( t2, out ) )
im_Lab2LabQ( t[1], out ) )
return( -1 );
return( 0 );
}
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_lab_morph", "%s",
_( "must be uncoded or IM_CODING_LABQ" ) );
return( -1 );
}
if( in->BandFmt != IM_BANDFMT_FLOAT && in->BandFmt != IM_BANDFMT_DOUBLE ) {
im_error( "im_lab_morph", "%s",
_( "must be uncoded float or double" ) );
return( -1 );
}
if( in->Bands != 3 ) {
im_error( "im_lab_morph", "%s",
_( "must be 3 bands" ) );
return( -1 );
}
if( !(parm = IM_NEW( out, Params )) ||
morph_init( parm,
in, out, L_scale, L_offset, mask, a_scale, b_scale ) )
return( -1 );
if( im_cp_desc( out, in ) )
return( -1 );
out->Type = IM_TYPE_LAB;
if( im_wrapone( in, out,
(im_wrapone_fn) morph_buffer, parm, NULL ) )
return( -1 );
return( 0 );
return( im__colour_unary( "im_lab_morph", in, out, IM_TYPE_LAB,
(im_wrapone_fn) morph_buffer, parm, NULL ) );
}

View File

@ -1,6 +1,8 @@
/* Convert Radiance 32bit packed format to float.
* 3/3/09
* - from LabQ2Lab and Radiance sources
* 2/11/09
* - gtkdoc
*/
/*
@ -167,15 +169,25 @@ rad2float( COLR *inp, COLOR *outbuf, int n )
}
}
/**
* im_rad2float:
* @in: input image
* @out: output image
*
* Unpack a RAD (#IM_CODING_RAD) image to a three-band float image.
*
* See also: im_rad2float(), im_LabQ2LabS().
*
* Returns: 0 on success, -1 on error.
*/
int
im_rad2float( IMAGE *in, IMAGE *out )
{
/* Must be 4-band uchar.
/* check for RAD coding
*/
if( in->Bands != 4 || in->BandFmt != IM_BANDFMT_UCHAR ||
in->Coding != IM_CODING_RAD ) {
im_error( "im_rad2float", "%s",
_( "4-band uchar Radiance-coded images only" ) );
if( in->Coding != IM_CODING_RAD ) {
im_error( "im_rad2float", "%s", _( "not a RAD image" ) );
return( -1 );
}
@ -183,7 +195,6 @@ im_rad2float( IMAGE *in, IMAGE *out )
return( -1 );
out->Bands = 3;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Bbits = im_bits_of_fmt( out->BandFmt );
out->Coding = IM_CODING_NONE;
if( im_wrapone( in, out,

View File

@ -326,6 +326,34 @@ static im_function remainderconst_vec_desc = {
remainderconst_vec_args /* Arg list */
};
static int
icc_export_vec( im_object *argv )
{
int intent = *((int *) argv[3]);
return( im_icc_export( argv[0], argv[1],
argv[2], intent ) );
}
static im_arg_desc icc_export_args[] = {
IM_INPUT_IMAGE( "in" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_STRING( "output_profile" ),
IM_INPUT_INT( "intent" )
};
/* Description of im_icc_export.
*/
static im_function icc_export_desc = {
"im_icc_export", /* Name */
"convert a float LAB to an 8-bit device image with an ICC profile",
/* Description */
IM_FN_PIO, /* Flags */
icc_export_vec, /* Dispatch function */
IM_NUMBER( icc_export_args ), /* Size of arg list */
icc_export_args /* Arg list */
};
/* Package up all these functions.
*/
static im_function *deprecated_list[] = {
@ -333,6 +361,7 @@ static im_function *deprecated_list[] = {
&remainderconst_vec_desc,
&fav4_desc,
&gadd_desc,
&icc_export_desc,
&litecor_desc,
&affine_desc,
&similarity_area_desc,

View File

@ -218,3 +218,11 @@ im_makerw( IMAGE *im )
{
return( im_rwcheck( im ) );
}
int
im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, VipsIntent intent )
{
return( im_icc_export_depth( in, out,
8, output_profile_filename, intent ) );
}

View File

@ -44,12 +44,6 @@ extern "C" {
#include <vips/util.h>
/* A colour temperature.
*/
typedef struct {
double X0, Y0, Z0;
} im_colour_temperature;
/* Areas under curves for Dxx. 2 degree observer.
*/
#define IM_D93_X0 (89.7400)
@ -128,7 +122,7 @@ int im_Lab2LCh( IMAGE *in, IMAGE *out );
int im_LCh2Lab( IMAGE *in, IMAGE *out );
int im_LabQ2XYZ( IMAGE *in, IMAGE *out );
int im_rad2float( IMAGE *in, IMAGE *out );
int im_float2rad( IMAGE *, IMAGE *out );
int im_float2rad( IMAGE *in, IMAGE *out );
int im_LCh2UCS( IMAGE *in, IMAGE *out );
int im_Lab2LCh( IMAGE *in, IMAGE *out );
int im_Lab2LabQ( IMAGE *in, IMAGE *out );
@ -163,23 +157,23 @@ int im_lab_morph( IMAGE *in, IMAGE *out,
/* Render intents for icc wrappers.
*/
#define IM_INTENT_PERCEPTUAL (0)
#define IM_INTENT_RELATIVE_COLORIMETRIC (1)
#define IM_INTENT_SATURATION (2)
#define IM_INTENT_ABSOLUTE_COLORIMETRIC (3)
typedef enum {
IM_INTENT_PERCEPTUAL = 0,
IM_INTENT_RELATIVE_COLORIMETRIC,
IM_INTENT_SATURATION,
IM_INTENT_ABSOLUTE_COLORIMETRIC
} VipsIntent;
int im_icc_present( void );
int im_icc_transform( IMAGE *in, IMAGE *out,
const char *input_profile_filename,
const char *output_profile_filename,
int intent );
VipsIntent intent );
int im_icc_import( IMAGE *in, IMAGE *out,
const char *input_profile_filename, int intent );
int im_icc_import_embedded( IMAGE *in, IMAGE *out, int intent );
int im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, int intent );
const char *input_profile_filename, VipsIntent intent );
int im_icc_import_embedded( IMAGE *in, IMAGE *out, VipsIntent intent );
int im_icc_export_depth( IMAGE *in, IMAGE *out, int depth,
const char *output_profile_filename, int intent );
const char *output_profile_filename, VipsIntent intent );
int im_icc_ac2rc( IMAGE *in, IMAGE *out, const char *profile_filename );
#ifdef __cplusplus

View File

@ -321,6 +321,11 @@ int im_similarity_area( IMAGE *in, IMAGE *out,
double a, double b, double dx, double dy,
int ox, int oy, int ow, int oh );
/* colour
*/
int im_icc_export( IMAGE *in, IMAGE *out,
const char *output_profile_filename, VipsIntent intent );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -166,11 +166,8 @@ int im__wrapscan( IMAGE *in,
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,
IMAGE *in, IMAGE *out, VipsType type,
im_wrapone_fn buffer_fn, void *a, void *b );
int im__test_kill( IMAGE *im );
@ -215,6 +212,13 @@ void im__black_region( REGION *reg );
void imb_Lab2LCh( float *, float *, int );
void imb_LCh2Lab( float *, float *, int );
void imb_XYZ2Lab_tables( void );
/* A colour temperature.
*/
typedef struct {
double X0, Y0, Z0;
} im_colour_temperature;
void imb_XYZ2Lab( float *, float *, int, im_colour_temperature * );
void imb_Lab2XYZ( float *, float *, int, im_colour_temperature * );
void imb_LabQ2Lab( PEL *, float *, int );