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:
parent
a93deb8201
commit
105760be0a
@ -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 );
|
||||||
}
|
|
||||||
|
|
||||||
if( vips_image_expected_bands( image ) !=
|
return( vips_blob_new( NULL, data, size ) );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load a profile from a blob and check compatibility.
|
||||||
|
*/
|
||||||
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_icc_profile_needs_bands( profile ) ) {
|
vips_image_expected_bands( image ) !=
|
||||||
|
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,
|
|
||||||
&data, &data_length ) ||
|
|
||||||
!(icc->out_profile = cmsOpenProfileFromMem(
|
|
||||||
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 );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if( !icc->out_blob &&
|
||||||
|
export->output_profile_filename ) {
|
||||||
|
icc->out_blob = vips_icc_get_profile_file(
|
||||||
|
export->output_profile_filename );
|
||||||
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,17 +1103,20 @@ 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" )) ) {
|
transform->output_profile_filename );
|
||||||
vips_error( class->nickname,
|
|
||||||
_( "unable to open profile \"%s\"" ),
|
|
||||||
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,
|
||||||
icc->in_profile, icc->intent, LCMS_USED_AS_INPUT );
|
icc->in_profile, icc->intent, LCMS_USED_AS_INPUT );
|
||||||
vips_check_intent( class->nickname,
|
vips_check_intent( class->nickname,
|
||||||
|
Loading…
Reference in New Issue
Block a user