seems to work

though the srgb fallback is not working

```
$ vips icc_import k2.jpg x.v --input-profile=srgb
vips__file_open_read: unable to open file "srgb" for reading
unix error: No such file or directory
icc_import: no input profile
```

perhaps padding issues?
This commit is contained in:
John Cupitt 2019-01-02 18:22:52 +00:00
parent a93deb8201
commit 105760be0a
1 changed files with 102 additions and 125 deletions

View File

@ -151,7 +151,9 @@ typedef struct _VipsIcc {
VipsPCS pcs; VipsPCS pcs;
int depth; int depth;
VipsBlob *in_blob;
cmsHPROFILE in_profile; cmsHPROFILE in_profile;
VipsBlob *out_blob;
cmsHPROFILE out_profile; cmsHPROFILE out_profile;
cmsUInt32Number in_icc_format; cmsUInt32Number in_icc_format;
cmsUInt32Number out_icc_format; cmsUInt32Number out_icc_format;
@ -181,6 +183,16 @@ vips_icc_dispose( GObject *gobject )
VIPS_FREEF( cmsCloseProfile, icc->in_profile ); VIPS_FREEF( cmsCloseProfile, icc->in_profile );
VIPS_FREEF( cmsCloseProfile, icc->out_profile ); VIPS_FREEF( cmsCloseProfile, icc->out_profile );
if( icc->in_blob ) {
vips_area_unref( (VipsArea *) icc->in_blob );
icc->in_blob = NULL;
}
if( icc->out_blob ) {
vips_area_unref( (VipsArea *) icc->out_blob );
icc->out_blob = NULL;
}
G_OBJECT_CLASS( vips_icc_parent_class )->dispose( gobject ); G_OBJECT_CLASS( vips_icc_parent_class )->dispose( gobject );
} }
@ -581,98 +593,72 @@ vips_image_expected_sig( VipsImage *image )
return( expected_sig ); return( expected_sig );
} }
static cmsHPROFILE /* Get from a filename, including loading a fallback.
vips_icc_load_profile_image( VipsImage *image ) */
static VipsBlob *
vips_icc_get_profile_file( const char *filename )
{ {
void *data; void *data;
size_t data_length; size_t size;
cmsHPROFILE profile;
if( (data = vips__fallback_profile_get( filename, &size )) )
/* We have a fallback profile of this name.
*/
return( vips_blob_new( NULL, data, size ) );
else if( (data = vips__file_read_name( filename,
vips__icc_dir(), &size )) )
/* Load from the named file.
*/
return( vips_blob_new(
(VipsCallbackFn) vips_free, data, size ) );
else
return( NULL );
}
/* Get from an image.
*/
static VipsBlob *
vips_icc_get_profile_image( VipsImage *image )
{
void *data;
size_t size;
if( !vips_image_get_typeof( image, VIPS_META_ICC_NAME ) ) if( !vips_image_get_typeof( image, VIPS_META_ICC_NAME ) )
return( NULL ); return( NULL );
if( vips_image_get_blob( image, VIPS_META_ICC_NAME, &data, &size ) )
if( vips_image_get_blob( image, VIPS_META_ICC_NAME,
&data, &data_length ) ||
!(profile = cmsOpenProfileFromMem( data, data_length )) ) {
g_warning( "%s", _( "corrupt embedded profile" ) );
return( NULL ); return( NULL );
return( vips_blob_new( NULL, data, size ) );
} }
if( vips_image_expected_bands( image ) != /* Load a profile from a blob and check compatibility.
vips_icc_profile_needs_bands( profile ) ) {
VIPS_FREEF( cmsCloseProfile, profile );
g_warning( "%s",
_( "embedded profile incompatible with image" ) );
return( NULL );
}
if( vips_image_expected_sig( image ) != cmsGetColorSpace( profile ) ) {
VIPS_FREEF( cmsCloseProfile, profile );
g_warning( "%s",
_( "embedded profile colourspace differs from image" ) );
return( NULL );
}
return( profile );
}
static void *
vips_icc_get_profile_file( const char *filename, size_t *data_length )
{
void *data;
/* See if we have a fallback profile of this name.
*/ */
if( (data = vips__fallback_profile_get( filename, data_length )) )
return( data );
/* Try to load as a filename.
*/
if( (data = vips__file_read_name( filename,
vips__icc_dir(), data_length )) )
return( data );
return( NULL );
}
static void *
vips_icc_get_profile_image( VipsImage *image, size_t *data_length )
{
void *data;
if( !vips_image_get_typeof( image, VIPS_META_ICC_NAME ) )
return( NULL );
if( vips_image_get_blob( image, VIPS_META_ICC_NAME,
&data, data_length ) _) {
g_warning( "%s", _( "corrupt embedded profile" ) );
return( NULL );
}
return( data );
}
static cmsHPROFILE static cmsHPROFILE
vips_icc_load_profile( const char *domain, vips_icc_load_profile_blob( VipsBlob *blob, VipsImage *image )
VipsImage *image, void *data, size_t *data_length )
{ {
const void *data;
size_t size;
cmsHPROFILE profile; cmsHPROFILE profile;
if( !(profile = cmsOpenProfileFromMem( data, data_length )) ) { data = vips_blob_get( blob, &size );
if( !(profile = cmsOpenProfileFromMem( data, size )) ) {
g_warning( "%s", _( "corrupt profile" ) ); g_warning( "%s", _( "corrupt profile" ) );
return( NULL ); return( NULL );
} }
if( vips_image_expected_bands( image ) != if( image &&
vips_image_expected_bands( image ) !=
vips_icc_profile_needs_bands( profile ) ) { vips_icc_profile_needs_bands( profile ) ) {
VIPS_FREEF( cmsCloseProfile, profile ); VIPS_FREEF( cmsCloseProfile, profile );
g_warning( _( "profile \"%s\" incompatible with image" ), g_warning( "%s", _( "profile incompatible with image" ) );
filename );
return( NULL ); return( NULL );
} }
if( vips_image_expected_sig( image ) != cmsGetColorSpace( profile ) ) { if( image &&
vips_image_expected_sig( image ) !=
cmsGetColorSpace( profile ) ) {
VIPS_FREEF( cmsCloseProfile, profile ); VIPS_FREEF( cmsCloseProfile, profile );
g_warning( _( "profile \"%s\" colourspace " g_warning( "%s",
"differs from image" ), filename ); _( "profile colourspace differs from image" ) );
return( NULL ); return( NULL );
} }
@ -695,23 +681,25 @@ vips_icc_import_build( VipsObject *object )
* 1 0 image * 1 0 image
* 0 1 file * 0 1 file
* 1 1 image, then fall back to file * 1 1 image, then fall back to file
*
* see also import_build.
*/ */
if( code->in && if( code->in &&
(import->embedded || (import->embedded ||
!import->input_profile_filename) ) !import->input_profile_filename) )
icc->in_profile = vips_icc_load_profile_image( code->in ); icc->in_blob = vips_icc_get_profile_image( code->in );
if( !icc->in_profile && if( !icc->in_blob &&
code->in &&
import->input_profile_filename ) { import->input_profile_filename ) {
icc->in_profile = vips_icc_load_profile_file( class->nickname, icc->in_blob = vips_icc_get_profile_file(
code->in, import->input_profile_filename ); import->input_profile_filename );
import->used_fallback = TRUE; import->used_fallback = TRUE;
} }
if( icc->in_blob &&
code->in )
icc->in_profile =
vips_icc_load_profile_blob( icc->in_blob, code->in );
if( !icc->in_profile ) { if( !icc->in_profile ) {
vips_error( class->nickname, "%s", _( "no input profile" ) ); vips_error( class->nickname, "%s", _( "no input profile" ) );
return( -1 ); return( -1 );
@ -733,23 +721,19 @@ vips_icc_import_build( VipsObject *object )
return( -1 ); return( -1 );
/* If we used the fallback profile, we need to attach it to the PCS /* If we used the fallback profile, we need to attach it to the PCS
* image since the PCS image needs to know about a route back to * image, since the PCS image needs a route back to device space.
* device space.
* *
* In the same way, we don't remove the embedded input profile on * In the same way, we don't remove the embedded input profile on
* import. * import.
*/ */
if( import->used_fallback ) { if( import->used_fallback &&
char *data; icc->in_blob ) {
size_t length; void *data;
size_t size;
if( !(data = vips__file_read_name(
import->input_profile_filename,
vips__icc_dir(), &length )) )
return( -1 );
data = vips_blob_get( icc->in_blob, &size );
vips_image_set_blob( colour->out, VIPS_META_ICC_NAME, vips_image_set_blob( colour->out, VIPS_META_ICC_NAME,
(VipsCallbackFn) vips_free, data, length ); NULL, data, size );
} }
return( 0 ); return( 0 );
@ -897,32 +881,18 @@ vips_icc_export_build( VipsObject *object )
icc->in_profile = cmsCreateXYZProfile(); icc->in_profile = cmsCreateXYZProfile();
if( code->in && if( code->in &&
!export->output_profile_filename && !export->output_profile_filename )
vips_image_get_typeof( code->in, VIPS_META_ICC_NAME ) ) { icc->out_blob = vips_icc_get_profile_image( code->in );
void *data;
size_t data_length;
if( vips_image_get_blob( code->in, VIPS_META_ICC_NAME, if( !icc->out_blob &&
&data, &data_length ) || export->output_profile_filename ) {
!(icc->out_profile = cmsOpenProfileFromMem( icc->out_blob = vips_icc_get_profile_file(
data, data_length )) ) {
vips_error( class->nickname,
"%s", _( "unable to load embedded profile" ) );
return( -1 );
}
}
else if( export->output_profile_filename ) {
if( !(icc->out_profile = cmsOpenProfileFromFile(
export->output_profile_filename, "r" )) ) {
vips_error( class->nickname,
_( "unable to open profile \"%s\"" ),
export->output_profile_filename ); export->output_profile_filename );
return( -1 );
}
colour->profile_filename = export->output_profile_filename; colour->profile_filename = export->output_profile_filename;
} }
else {
if( !(icc->out_profile =
vips_icc_load_profile_blob( icc->out_blob, NULL )) ) {
vips_error( class->nickname, "%s", _( "no output profile" ) ); vips_error( class->nickname, "%s", _( "no output profile" ) );
return( -1 ); return( -1 );
} }
@ -1115,13 +1085,17 @@ vips_icc_transform_build( VipsObject *object )
if( code->in && if( code->in &&
(transform->embedded || (transform->embedded ||
!transform->input_profile_filename) ) !transform->input_profile_filename) )
icc->in_profile = vips_icc_load_profile_image( code->in ); icc->in_blob = vips_icc_get_profile_image( code->in );
if( !icc->in_profile && if( !icc->in_blob &&
code->in &&
transform->input_profile_filename ) transform->input_profile_filename )
icc->in_profile = vips_icc_load_profile_file( class->nickname, icc->in_blob = vips_icc_get_profile_file(
code->in, transform->input_profile_filename ); transform->input_profile_filename );
if( icc->in_blob &&
code->in )
icc->in_profile =
vips_icc_load_profile_blob( icc->in_blob, code->in );
if( !icc->in_profile ) { if( !icc->in_profile ) {
vips_error( class->nickname, "%s", _( "no input profile" ) ); vips_error( class->nickname, "%s", _( "no input profile" ) );
@ -1129,15 +1103,18 @@ vips_icc_transform_build( VipsObject *object )
} }
if( transform->output_profile_filename ) { if( transform->output_profile_filename ) {
if( !(icc->out_profile = cmsOpenProfileFromFile( icc->out_blob = vips_icc_get_profile_file(
transform->output_profile_filename, "r" )) ) {
vips_error( class->nickname,
_( "unable to open profile \"%s\"" ),
transform->output_profile_filename ); transform->output_profile_filename );
return( -1 ); colour->profile_filename = transform->output_profile_filename;
} }
colour->profile_filename = transform->output_profile_filename; if( icc->out_blob )
icc->out_profile =
vips_icc_load_profile_blob( icc->out_blob, NULL );
if( !icc->out_profile ) {
vips_error( class->nickname, "%s", _( "no output profile" ) );
return( -1 );
} }
vips_check_intent( class->nickname, vips_check_intent( class->nickname,