add exif support to png load/save (#3168)

* start adding exif in png

the "Exif\0\0" header isn't being added and removed correctly

needs tests

* all done

tested with linpng and libspng
This commit is contained in:
John Cupitt 2022-11-18 11:57:05 +00:00 committed by GitHub
parent ef1300a288
commit e3289ad2c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 2 deletions

View File

@ -23,6 +23,7 @@ master
- fits write doesn't duplicate header fields
- add @wrap to vips_text()
- GIF load supports truncated frames [tlsa]
- EXIF support for PNG load and save
9/11/22 started 8.13.4
- missing include in mosaic_fuzzer [ServOKio]

View File

@ -12,6 +12,8 @@
* - use libspng for save
* 15/7/22 [lovell]
* - default filter to none
* 17/11/22
* - add exif save
*/
/*
@ -56,6 +58,7 @@
#include <string.h>
#include <vips/vips.h>
#include <vips/internal.h>
#include "pforeign.h"
#include "quantise.h"
@ -244,6 +247,25 @@ vips_foreign_save_spng_metadata( VipsForeignSaveSpng *spng, VipsImage *in )
g_free( str );
}
if( vips_image_get_typeof( in, VIPS_META_EXIF_NAME ) ) {
struct spng_exif exif;
if( vips__exif_update( in ) ||
vips_image_get_blob( in, VIPS_META_EXIF_NAME,
(const void **) &exif.data, &exif.length ) )
return( -1 );
/* libspng does not want the JFIF "Exif\0\0" prefix.
*/
if( exif.length >= 6 &&
vips_isprefix( "Exif", exif.data ) ) {
exif.data += 6;
exif.length -= 6;
}
spng_set_exif( spng->ctx, &exif );
}
if( vips_image_map( in, vips_foreign_save_spng_comment, spng ) )
return( -1 );

View File

@ -85,6 +85,8 @@
* - add "unlimited" flag to png load
* 13/1/22
* - raise libpng pixel size limit to VIPS_MAX_COORD
* 17/11/22
* - add exif read/write
*/
/*
@ -638,6 +640,17 @@ png2vips_header( Read *read, VipsImage *out )
}
#endif /*PNG_bKGD_SUPPORTED*/
#ifdef PNG_eXIf_SUPPORTED
{
png_uint_32 num_exif;
png_bytep exif;
if( png_get_eXIf_1( read->pPng, read->pInfo, &num_exif, &exif ) )
vips_image_set_blob_copy( out, VIPS_META_EXIF_NAME,
exif, num_exif );
}
#endif /*PNG_eXIf_SUPPORTED*/
return( 0 );
}
@ -1173,8 +1186,30 @@ write_vips( Write *write,
g_free( str );
}
if( vips_image_map( in,
write_png_comment, write ) )
#ifdef PNG_eXIf_SUPPORTED
if( vips_image_get_typeof( in, VIPS_META_EXIF_NAME ) ) {
const void *data;
size_t length;
if( vips__exif_update( in ) ||
vips_image_get_blob( in, VIPS_META_EXIF_NAME,
&data, &length ) )
return( -1 );
/* libpng does not want the JFIF "Exif\0\0" prefix.
*/
if( length >= 6 &&
vips_isprefix( "Exif", (char *) data ) ) {
data += 6;
length -= 6;
}
png_set_eXIf_1( write->pPng, write->pInfo,
length, (png_bytep) data );
}
#endif /*PNG_eXIf_SUPPORTED*/
if( vips_image_map( in, write_png_comment, write ) )
return( -1 );
}

View File

@ -457,6 +457,25 @@ class TestForeign:
# we can't test palette save since we can't be sure libimagequant is
# available and there's no easy test for its presence
# see if we have exif parsing: our test jpg image has this field
x = pyvips.Image.new_from_file(JPEG_FILE)
if x.get_typeof("exif-ifd0-Orientation") != 0:
# we need a copy of the image to set the new metadata on
# otherwise we get caching problems
# can set, save and load new orientation
x = pyvips.Image.new_from_file(JPEG_FILE)
x = x.copy()
x.set("orientation", 2)
filename = temp_filename(self.tempdir, '.png')
x.write_to_file(filename)
x = pyvips.Image.new_from_file(filename)
y = x.get("orientation")
assert y == 2
@skip_if_no("tiffload")
def test_tiff(self):
def tiff_valid(im):