diff --git a/libvips/colour/CMYK2XYZ.c b/libvips/colour/CMYK2XYZ.c index 83e2603c..0abc074b 100644 --- a/libvips/colour/CMYK2XYZ.c +++ b/libvips/colour/CMYK2XYZ.c @@ -45,8 +45,8 @@ #include #include -#include "pcolour.h" #include "profiles.h" +#include "pcolour.h" typedef struct _VipsCMYK2XYZ { VipsOperation parent_instance; @@ -61,40 +61,66 @@ G_DEFINE_TYPE( VipsCMYK2XYZ, vips_CMYK2XYZ, VIPS_TYPE_OPERATION ); /* Created on first use from a base64 string in profiles.c. */ -static void *vips_CMYK2XYZ_fallback_profile = NULL; -static size_t vips_CMYK2XYZ_fallback_profile_length = 0; +typedef struct _VipsFallbackProfile { + const char *name; + void *data; + size_t data_length; +} VipsFallbackProfile; + +static GSList *vips_fallback_profile_list = NULL; static void * -vips_CMYK2XYZ_get_fallback_profile_init( void ) +vips__fallback_profile_get_init( void ) { - size_t data_length; - unsigned char *data; + int i; - if( !(data = vips__b64_decode( vips__coded_cmyk, &data_length )) ) - return( NULL ); - vips_CMYK2XYZ_fallback_profile = data; - vips_CMYK2XYZ_fallback_profile_length = data_length; + for( i = 0; vips__coded_profiles[i].name; i++ ) { + size_t data_length; + unsigned char *data; + VipsFallbackProfile *fallback; + + if( !(data = vips__b64_decode( + vips__coded_profiles[i].data, &data_length )) ) + return( NULL ); + fallback = g_new( VipsFallbackProfile,1 ); + fallback->name = vips__coded_profiles[i].name; + fallback->data = data; + fallback->data_length = data_length; + vips_fallback_profile_list = g_slist_append( + vips_fallback_profile_list, fallback ); + } return( NULL ); } -static void * -vips__CMYK2XYZ_get_fallback_profile( size_t *length ) +/* Shared with icc_transform.c + */ +void * +vips__fallback_profile_get( const char *name, size_t *length ) { GOnce once = G_ONCE_INIT; - VIPS_ONCE( &once, - (GThreadFunc) vips_CMYK2XYZ_get_fallback_profile_init, NULL ); + GSList *p; - *length = vips_CMYK2XYZ_fallback_profile_length; + VIPS_ONCE( &once, (GThreadFunc) vips__fallback_profile_get_init, NULL ); - return( vips_CMYK2XYZ_fallback_profile ); + for( p = vips_fallback_profile_list; p; p = p->next ) { + VipsFallbackProfile *fallback = (VipsFallbackProfile *) p->data; + + if( strcasecmp( fallback->name, name ) == 0 ) { + *length = fallback->data_length; + + return( fallback->data ); + } + } + + return( NULL ); } /* Shared with XYZ2CMYK.c. */ int -vips_CMYK2XYZ_set_fallback_profile( VipsImage *image ) +vips__fallback_profile_set( const char *name, VipsImage *image ) { size_t data_length; unsigned char *data; @@ -105,8 +131,11 @@ vips_CMYK2XYZ_set_fallback_profile( VipsImage *image ) if( vips_image_get_typeof( image, VIPS_META_ICC_NAME ) ) return( 0 ); - if( !(data = vips__CMYK2XYZ_get_fallback_profile( &data_length )) ) + if( !(data = vips__fallback_profile_get( name, &data_length )) ) { + vips_error( "fallback", + _( "unknown fallback profile \"%s\"" ), name ); return( -1 ); + } vips_image_set_blob( image, VIPS_META_ICC_NAME, NULL, data, data_length ); @@ -140,7 +169,7 @@ vips_CMYK2XYZ_build( VipsObject *object ) g_object_set( object, "out", out, NULL ); if( vips_copy( CMYK2XYZ->in, &t[0], NULL ) || - vips_CMYK2XYZ_set_fallback_profile( t[0] ) || + vips__fallback_profile_set( "cmyk", t[0] ) || vips__colourspace_process_n( "CMYK2XYZ", t[0], &t[1], 4, vips_CMYK2XYZ_process ) || vips_image_write( t[1], out ) ) diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index 09d8b55e..4aeb5499 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -1,13 +1,14 @@ noinst_LTLIBRARIES = libcolour.la if ENABLE_LCMS -PROFILES = profiles.c profiles.h +PROFILES = profiles.c else PROFILES = endif libcolour_la_SOURCES = \ $(PROFILES) \ + profiles.h \ colour.c \ pcolour.h \ CMYK2XYZ.c \ @@ -43,7 +44,7 @@ libcolour_la_SOURCES = \ scRGB2sRGB.c profiles.c: - ./wrap_profiles.sh profiles profiles + ./wrap_profiles.sh profiles profiles.c EXTRA_DIST = \ profiles \ diff --git a/libvips/colour/XYZ2CMYK.c b/libvips/colour/XYZ2CMYK.c index bf5cd2b3..d7737399 100644 --- a/libvips/colour/XYZ2CMYK.c +++ b/libvips/colour/XYZ2CMYK.c @@ -84,7 +84,7 @@ vips_XYZ2CMYK_build( VipsObject *object ) g_object_set( object, "out", out, NULL ); if( vips_copy( XYZ2CMYK->in, &t[0], NULL ) || - vips_CMYK2XYZ_set_fallback_profile( t[0] ) || + vips__fallback_profile_set( "cmyk", t[0] ) || vips__colourspace_process_n( "XYZ2CMYK", t[0], &t[1], 3, vips_XYZ2CMYK_process ) || vips_image_write( t[1], out ) ) diff --git a/libvips/colour/icc_transform.c b/libvips/colour/icc_transform.c index 49b40caf..fec7d89b 100644 --- a/libvips/colour/icc_transform.c +++ b/libvips/colour/icc_transform.c @@ -615,16 +615,51 @@ vips_icc_load_profile_image( VipsImage *image ) 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 -vips_icc_load_profile_file( const char *domain, - VipsImage *image, const char *filename ) +vips_icc_load_profile( const char *domain, + VipsImage *image, void *data, size_t *data_length ) { cmsHPROFILE profile; - if( !(profile = cmsOpenProfileFromFile( filename, "r" )) ) { - vips_error( domain, - _( "unable to open profile \"%s\"" ), filename ); - return( NULL ); + if( !(profile = cmsOpenProfileFromMem( data, data_length )) ) { + g_warning( "%s", _( "corrupt profile" ) ); + return( NULL ); } if( vips_image_expected_bands( image ) != diff --git a/libvips/colour/pcolour.h b/libvips/colour/pcolour.h index da93c9c6..475c3bb4 100644 --- a/libvips/colour/pcolour.h +++ b/libvips/colour/pcolour.h @@ -216,7 +216,8 @@ extern float vips_v2Y_16[65536]; void vips_col_make_tables_RGB_8( void ); void vips_col_make_tables_RGB_16( void ); -int vips_CMYK2XYZ_set_fallback_profile( VipsImage *image ); +void *vips__fallback_profile_get( const char *name, size_t *length ); +int vips__fallback_profile_set( const char *name, VipsImage *image ); /* A colour-transforming function. */ diff --git a/libvips/colour/profiles.c b/libvips/colour/profiles.c index 0550c9e7..e064fa74 100644 --- a/libvips/colour/profiles.c +++ b/libvips/colour/profiles.c @@ -1,6 +1,9 @@ /* coded files, generated automatically */ -char *vips__coded_cmyk = +#include "profiles.h" + +VipsCodedProfile vips__coded_profiles[] = { + { "cmyk", "AA6sbGFyZ2wCIAAAcHJ0ckNNWUtMYWIgB94ACAAZAAwAKAA1YWNzcE1TRlQAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAEAAPbWAAEAAAAA0y1hcmdsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAPZGVzYwAAATgAAABpY3BydAAAAaQAAABnd3RwdAAAAgwAAAAUYmtw" @@ -16872,4 +16875,6 @@ char *vips__coded_cmyk = "LjI5IDMuOTIgMy41NyAzLjIzIDMuMDUgMy40IDQuMjUgNC43NCAzLjc1IDIuNDggMS45NCAxLjcz" "IDEuNDYgMS40IDEuODMgMi41OCAyLjk0IDIuOTUgMi45NCAyLjk1IDIuOTggMy4zMiAzLjk5IDQu" "NDIgNC4yOCAzLjk0IDMuNDcgMy4xMyAzLjM1IDQuMjENCkVORF9EQVRBDQoNCg0KDQoNCgAA" -; + }, + { 0, 0 } +}; diff --git a/libvips/colour/profiles.h b/libvips/colour/profiles.h index 25db4062..e958e6b4 100644 --- a/libvips/colour/profiles.h +++ b/libvips/colour/profiles.h @@ -1,3 +1,10 @@ -/* header for coded files, generated automatically */ +/* The fallback profiles, coded as a set of base64 strings, see + * wrap-profiles.sh + */ +typedef struct _VipsCodedProfile { + const char *name; + const char *data; +} VipsCodedProfile; + +extern VipsCodedProfile vips__coded_profiles[]; -extern char *vips__coded_cmyk ; diff --git a/libvips/colour/profiles/sRGB.icm b/libvips/colour/profiles/sRGB.icm new file mode 100644 index 00000000..1d8f7419 Binary files /dev/null and b/libvips/colour/profiles/sRGB.icm differ diff --git a/libvips/colour/wrap-profiles.sh b/libvips/colour/wrap-profiles.sh index fcfd422f..cfd801b9 100755 --- a/libvips/colour/wrap-profiles.sh +++ b/libvips/colour/wrap-profiles.sh @@ -1,27 +1,22 @@ #!/bin/bash -# code up the binary files in $1 as a set of base64-encoded strings in $2 +# code up the binary files in $1 as a set of name / base64-encoded strings +# in $2 in=$1 -out_c=$2.c -out_h=$2.h +out=$2 -echo "/* coded files, generated automatically */" > $out_c -echo "" >> $out_c +echo "/* coded files, generated automatically */" > $out +echo "" >> $out +echo "#include \"profiles.h\"" >> $out +echo "" >> $out +echo "VipsCodedProfile vips__coded_profiles[] = {" >> $out for file in $in/*; do root=${file%.icm} base=${root##*/} - echo char \*vips__coded_$base = >> $out_c - base64 $file | sed 's/\(.*\)/"\1"/g' >> $out_c - echo ';' >> $out_c + echo " { \"$base\"," >> $out + base64 $file | sed 's/\(.*\)/"\1"/g' >> $out + echo " }," >> $out done - -echo "/* header for coded files, generated automatically */" > $out_h -echo "" >> $out_h -for file in $in/*; do - root=${file%.icm} - base=${root##*/} - echo extern char \*vips__coded_$base ';' >> $out_h -done - - +echo " { 0, 0 }" >> $out +echo "};" >> $out