16-bit sRGB -> XYZ works

This commit is contained in:
John Cupitt 2012-11-06 13:30:30 +00:00
parent cb4965536d
commit 2ffbcb709c
4 changed files with 66 additions and 15 deletions

View File

@ -86,7 +86,7 @@ static float vips_v2Y_16[65536];
* The matrix already includes the D65 channel weighting, so we just scale by
* Y.
*/
#define SCALE (VIPS_D65_Y0 / 3.0)
#define SCALE (VIPS_D65_Y0)
/* linear RGB -> XYZ matrix.
*/

View File

@ -164,10 +164,19 @@ static VipsColourRoute vips_colour_routes[] = {
gboolean
vips_colourspace_issupported( const VipsImage *image )
{
VipsInterpretation interpretation =
vips_image_guess_interpretation( image );
VipsInterpretation interpretation;
int i;
/* Treat RGB and RGB16 as sRGB. If you want some other treatment,
* you'll need to use the icc funcs.
*
* sRGB2XYZ can handle 8 and 16-bit images.
*/
interpretation = vips_image_guess_interpretation( image );
if( interpretation == VIPS_INTERPRETATION_RGB ||
interpretation == VIPS_INTERPRETATION_RGB16 )
interpretation = VIPS_INTERPRETATION_sRGB;
for( i = 0; i < VIPS_NUMBER( vips_colour_routes ); i++ )
if( vips_colour_routes[i].from == interpretation )
return( TRUE );
@ -209,6 +218,15 @@ vips_colourspace_build( VipsObject *object )
interpretation = vips_image_guess_interpretation( colourspace->in );
/* Treat RGB and RGB16 as sRGB. If you want some other treatment,
* you'll need to use the icc funcs.
*
* sRGB2XYZ can handle 8 and 16-bit images.
*/
if( interpretation == VIPS_INTERPRETATION_RGB ||
interpretation == VIPS_INTERPRETATION_RGB16 )
interpretation = VIPS_INTERPRETATION_sRGB;
/* No conversion necessary.
*/
if( interpretation == colourspace->space ) {

View File

@ -234,8 +234,13 @@ vips_icc_build( VipsObject *object )
if( icc->out_profile )
switch( cmsGetColorSpace( icc->out_profile ) ) {
case icSigRgbData:
colour->interpretation = VIPS_INTERPRETATION_RGB;
colour->format = VIPS_FORMAT_UCHAR;
colour->interpretation =
icc->depth == 8 ?
VIPS_INTERPRETATION_RGB :
VIPS_INTERPRETATION_RGB16;
colour->format =
icc->depth == 8 ?
VIPS_FORMAT_UCHAR : VIPS_FORMAT_USHORT;
colour->bands = 3;
icc->out_icc_format =
icc->depth == 16 ?

View File

@ -9,6 +9,8 @@
* 21/9/12
* - redone as a class
* - sRGB only, support for other RGBs is now via lcms
* 6/11/12
* - add 15-bit sRGB import
*/
/*
@ -57,12 +59,8 @@ G_DEFINE_TYPE( VipssRGB2XYZ, vips_sRGB2XYZ, VIPS_TYPE_COLOUR_CODE );
/* Convert a buffer of 8-bit pixels.
*/
static void
vips_sRGB2XYZ_line_8( VipsColour *colour,
VipsPel *out, VipsPel **in, int width )
vips_sRGB2XYZ_line_8( float *q, VipsPel *p, int width )
{
VipsPel *p = in[0];
float *q = (float *) out;
int i;
for( i = 0; i < width; i++ ) {
@ -86,12 +84,8 @@ vips_sRGB2XYZ_line_8( VipsColour *colour,
/* Convert a buffer of 16-bit pixels.
*/
static void
vips_sRGB2XYZ_line_16( VipsColour *colour,
VipsPel *out, VipsPel **in, int width )
vips_sRGB2XYZ_line_16( float *q, unsigned short *p, int width )
{
unsigned short *p = in[0];
float *q = (float *) out;
int i;
for( i = 0; i < width; i++ ) {
@ -112,6 +106,35 @@ vips_sRGB2XYZ_line_16( VipsColour *colour,
}
}
static void
vips_sRGB2XYZ_line( VipsColour *colour,
VipsPel *out, VipsPel **in, int width )
{
if( colour->in[0]->BandFmt == VIPS_FORMAT_UCHAR )
vips_sRGB2XYZ_line_8( (float *) out,
(VipsPel *) in[0], width );
else
vips_sRGB2XYZ_line_16( (float *) out,
(unsigned short *) in[0], width );
}
static int
vips_sRGB2XYZ_build( VipsObject *object )
{
VipsColourCode *code = (VipsColourCode *) object;
if( code->in )
code->input_format =
code->in->BandFmt == VIPS_FORMAT_USHORT ?
VIPS_FORMAT_USHORT : VIPS_FORMAT_UCHAR;
if( VIPS_OBJECT_CLASS( vips_sRGB2XYZ_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static void
vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class )
{
@ -120,6 +143,7 @@ vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class )
object_class->nickname = "sRGB2XYZ";
object_class->description = _( "convert an sRGB image to XYZ" );
object_class->build = vips_sRGB2XYZ_build;
colour_class->process_line = vips_sRGB2XYZ_line;
}
@ -137,6 +161,10 @@ vips_sRGB2XYZ_init( VipssRGB2XYZ *sRGB2XYZ )
code->input_coding = VIPS_CODING_NONE;
code->input_bands = 3;
/* The default. This can get changed above ^^ if we see a
* 16-bit input.
*/
code->input_format = VIPS_FORMAT_UCHAR;
}