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 * The matrix already includes the D65 channel weighting, so we just scale by
* Y. * Y.
*/ */
#define SCALE (VIPS_D65_Y0 / 3.0) #define SCALE (VIPS_D65_Y0)
/* linear RGB -> XYZ matrix. /* linear RGB -> XYZ matrix.
*/ */

View File

@ -164,10 +164,19 @@ static VipsColourRoute vips_colour_routes[] = {
gboolean gboolean
vips_colourspace_issupported( const VipsImage *image ) vips_colourspace_issupported( const VipsImage *image )
{ {
VipsInterpretation interpretation = VipsInterpretation interpretation;
vips_image_guess_interpretation( image );
int i; 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++ ) for( i = 0; i < VIPS_NUMBER( vips_colour_routes ); i++ )
if( vips_colour_routes[i].from == interpretation ) if( vips_colour_routes[i].from == interpretation )
return( TRUE ); return( TRUE );
@ -209,6 +218,15 @@ vips_colourspace_build( VipsObject *object )
interpretation = vips_image_guess_interpretation( colourspace->in ); 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. /* No conversion necessary.
*/ */
if( interpretation == colourspace->space ) { if( interpretation == colourspace->space ) {

View File

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

View File

@ -9,6 +9,8 @@
* 21/9/12 * 21/9/12
* - redone as a class * - redone as a class
* - sRGB only, support for other RGBs is now via lcms * - 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. /* Convert a buffer of 8-bit pixels.
*/ */
static void static void
vips_sRGB2XYZ_line_8( VipsColour *colour, vips_sRGB2XYZ_line_8( float *q, VipsPel *p, int width )
VipsPel *out, VipsPel **in, int width )
{ {
VipsPel *p = in[0];
float *q = (float *) out;
int i; int i;
for( i = 0; i < width; i++ ) { for( i = 0; i < width; i++ ) {
@ -86,12 +84,8 @@ vips_sRGB2XYZ_line_8( VipsColour *colour,
/* Convert a buffer of 16-bit pixels. /* Convert a buffer of 16-bit pixels.
*/ */
static void static void
vips_sRGB2XYZ_line_16( VipsColour *colour, vips_sRGB2XYZ_line_16( float *q, unsigned short *p, int width )
VipsPel *out, VipsPel **in, int width )
{ {
unsigned short *p = in[0];
float *q = (float *) out;
int i; int i;
for( i = 0; i < width; 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 static void
vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class ) vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class )
{ {
@ -120,6 +143,7 @@ vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class )
object_class->nickname = "sRGB2XYZ"; object_class->nickname = "sRGB2XYZ";
object_class->description = _( "convert an sRGB image to XYZ" ); object_class->description = _( "convert an sRGB image to XYZ" );
object_class->build = vips_sRGB2XYZ_build;
colour_class->process_line = vips_sRGB2XYZ_line; colour_class->process_line = vips_sRGB2XYZ_line;
} }
@ -137,6 +161,10 @@ vips_sRGB2XYZ_init( VipssRGB2XYZ *sRGB2XYZ )
code->input_coding = VIPS_CODING_NONE; code->input_coding = VIPS_CODING_NONE;
code->input_bands = 3; code->input_bands = 3;
/* The default. This can get changed above ^^ if we see a
* 16-bit input.
*/
code->input_format = VIPS_FORMAT_UCHAR; code->input_format = VIPS_FORMAT_UCHAR;
} }