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:
parent
ef1300a288
commit
e3289ad2c1
@ -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]
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user