From 75e155e141ba4c926f178e8bb2744cf0f3c82fba Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Thu, 13 Dec 2018 11:15:10 +1100 Subject: [PATCH] move EXIF handling from the JPEG handler to core Imager and add it to the API. The JPEG specific check was removed from the EXIF handling code and inlined into the APP1 check in the JPEG decoder. --- Changes | 9 +++++++++ JPEG/JPEG.pm | 2 +- JPEG/MANIFEST | 2 -- JPEG/Makefile.PL | 4 ++-- JPEG/imjpeg.c | 7 +++++-- MANIFEST | 4 ++-- Makefile.PL | 2 +- JPEG/imexif.c => imexif.c | 24 ++++++++---------------- JPEG/imexif.h => imexif.h | 2 +- imext.c | 9 +++++++-- imext.h | 2 ++ imexttypes.h | 5 ++++- lib/Imager/APIRef.pod | 19 +++++++++++++++++++ xt/x20spell.t | 1 + 14 files changed, 62 insertions(+), 30 deletions(-) rename JPEG/imexif.c => imexif.c (98%) rename JPEG/imexif.h => imexif.h (69%) diff --git a/Changes b/Changes index c8f0197c..3a4e9bea 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,14 @@ Imager release history. Older releases can be found in Changes.old + - moved EXIF handling from Imager::File::JPEG to core Imager + + - added some more file extension to image file type mappings + + - added add_type_extensions() class method + +Imager 1.007 +============ + - add png_compression_level tag for writing PNG files. - avoid flooring a second time in matrix transform interpolation. diff --git a/JPEG/JPEG.pm b/JPEG/JPEG.pm index ffedae64..3ac30296 100644 --- a/JPEG/JPEG.pm +++ b/JPEG/JPEG.pm @@ -4,7 +4,7 @@ use Imager; use vars qw($VERSION @ISA); BEGIN { - $VERSION = "0.91"; + $VERSION = "0.92"; require XSLoader; XSLoader::load('Imager::File::JPEG', $VERSION); diff --git a/JPEG/MANIFEST b/JPEG/MANIFEST index 43fd14f7..b53bc154 100644 --- a/JPEG/MANIFEST +++ b/JPEG/MANIFEST @@ -1,6 +1,4 @@ Changes -imexif.c -imexif.h imjpeg.c imjpeg.h inc/Devel/CheckLib.pm diff --git a/JPEG/Makefile.PL b/JPEG/Makefile.PL index 14a13417..ab5a8615 100644 --- a/JPEG/Makefile.PL +++ b/JPEG/Makefile.PL @@ -19,7 +19,7 @@ my %opts = ( NAME => 'Imager::File::JPEG', VERSION_FROM => 'JPEG.pm', - OBJECT => 'JPEG.o imjpeg.o imexif.o', + OBJECT => 'JPEG.o imjpeg.o', clean => { FILES => 'testout' }, ); @@ -65,7 +65,7 @@ else { $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ]; # Imager required configure through use - my @Imager_req = ( Imager => "0.86" ); + my @Imager_req = ( Imager => "1.008" ); if (eval { ExtUtils::MakeMaker->VERSION('6.46'); 1 }) { $opts{META_MERGE}{prereqs} = { diff --git a/JPEG/imjpeg.c b/JPEG/imjpeg.c index dcb0ed63..35b3a1c4 100644 --- a/JPEG/imjpeg.c +++ b/JPEG/imjpeg.c @@ -34,7 +34,6 @@ Reads and writes JPEG images #include "jerror.h" #include #include -#include "imexif.h" #define JPEG_APP13 0xED /* APP13 marker code */ #define JPEG_APP1 (JPEG_APP0 + 1) @@ -495,7 +494,11 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) { markerp->data_length); } else if (markerp->marker == JPEG_APP1 && !seen_exif) { - seen_exif = i_int_decode_exif(im, markerp->data, markerp->data_length); + unsigned char *data = markerp->data; + size_t len = markerp->data_length; + if (len >= 6 && memcmp(data, "Exif\0\0", 6) == 0) { + seen_exif = im_decode_exif(im, data+6, len-6); + } } else if (markerp->marker == JPEG_APP13) { *iptc_itext = mymalloc(markerp->data_length); diff --git a/MANIFEST b/MANIFEST index 41825da4..85bdac6b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -135,6 +135,8 @@ Imager.xs imageri.h imdatatypes.h imerror.h Error handling functions +imexif.c EXIF decoding +imexif.h imext.c Defines the function table imext.h Included by external modules for API access imextdef.h @@ -154,8 +156,6 @@ io.c iolayer.c iolayer.h iolayert.h IO layer types -JPEG/imexif.c Experimental JPEG EXIF decoding -JPEG/imexif.h JPEG/imjpeg.c JPEG/imjpeg.h JPEG/JPEG.pm diff --git a/Makefile.PL b/Makefile.PL index 2b14c27f..80ceb994 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -150,7 +150,7 @@ my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o imext.o scale.o rubthru.o render.o paste.o compose.o flip.o - perlio.o); + perlio.o imexif.o); my $lib_define = ''; my $lib_inc = ''; diff --git a/JPEG/imexif.c b/imexif.c similarity index 98% rename from JPEG/imexif.c rename to imexif.c index 8cb90b78..4bdf386a 100644 --- a/JPEG/imexif.c +++ b/imexif.c @@ -1,4 +1,4 @@ -#include "imext.h" +#include "imager.h" #include "imexif.h" #include #include @@ -12,7 +12,7 @@ imexif.c - EXIF support for Imager =head1 SYNOPSIS - if (i_int_decode_exif(im, app1data, app1datasize)) { + if (im_decode_exif(im, app1data, app1datasize)) { // exif block seen } @@ -267,12 +267,12 @@ intended to be called from outside of Imager. =over -=item i_int_decode_exit +=item im_decode_exif -i_int_decode_exif(im, data_base, data_size); +im_decode_exif(im, data_base, data_size); -The data from data_base for data_size bytes will be scanned for EXIF -data. +The data from C for C bytes will be scanned for +EXIF data. Any data found will be used to set tags in the supplied image. @@ -280,24 +280,16 @@ The intent is that invalid EXIF data will simply fail to set tags, and write to the log. In no case should this code exit when supplied invalid data. -Returns true if an Exif header was seen. +Returns true if an EXIF header was seen. =cut */ int -i_int_decode_exif(i_img *im, unsigned char *data, size_t length) { +im_decode_exif(i_img *im, unsigned char *data, size_t length) { imtiff tiff; unsigned long exif_ifd_offset = 0; unsigned long gps_ifd_offset = 0; - /* basic checks - must start with "Exif\0\0" */ - - if (length < 6 || memcmp(data, "Exif\0\0", 6) != 0) { - return 0; - } - - data += 6; - length -= 6; if (!tiff_init(&tiff, data, length)) { mm_log((2, "Exif header found, but no valid TIFF header\n")); diff --git a/JPEG/imexif.h b/imexif.h similarity index 69% rename from JPEG/imexif.h rename to imexif.h index e5f332a6..2e02d1d2 100644 --- a/JPEG/imexif.h +++ b/imexif.h @@ -5,6 +5,6 @@ #include #include "imdatatypes.h" -extern int i_int_decode_exif(i_img *im, unsigned char *data, size_t length); +extern int im_decode_exif(i_img *im, unsigned char *data, size_t length); #endif /* ifndef IMAGER_IMEXIF_H */ diff --git a/imext.c b/imext.c index 36ba2b62..b1ce6188 100644 --- a/imext.c +++ b/imext.c @@ -1,6 +1,7 @@ #include "imexttypes.h" #include "imager.h" #include "imio.h" +#include "imexif.h" static im_context_t get_context(void); static i_img *mathom_i_img_8_new(i_img_dim, i_img_dim, int); @@ -212,10 +213,14 @@ im_ext_funcs imager_function_table = i_poly_aa_m, i_poly_aa_cfill_m, - /* level 10 */ i_img_alpha_channel, i_img_color_model, - i_img_color_channels + i_img_color_channels, + + /* level 10 */ + im_decode_exif + + /* level 11 */ }; /* in general these functions aren't called by Imager internally, but diff --git a/imext.h b/imext.h index c288a423..bc7bae81 100644 --- a/imext.h +++ b/imext.h @@ -247,6 +247,8 @@ extern im_ext_funcs *imager_function_ext_table; #define i_img_color_model(im) ((im_extt->f_i_img_color_model)((im))) #define i_img_color_channels(im) ((im_extt->f_i_img_color_channels)((im))) +#define im_decode_exif(im, data, len) ((im_extt->f_im_decode_exif)((im), (data), (len))) + #ifdef IMAGER_LOG #ifndef IMAGER_NO_CONTEXT #define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; } diff --git a/imexttypes.h b/imexttypes.h index ebbc9c38..62e325ba 100644 --- a/imexttypes.h +++ b/imexttypes.h @@ -34,7 +34,7 @@ will result in an increment of IMAGER_API_LEVEL. */ -#define IMAGER_API_LEVEL 9 +#define IMAGER_API_LEVEL 10 typedef struct { int version; @@ -271,6 +271,9 @@ typedef struct { int (*f_i_img_color_channels)(i_img *im); /* IMAGER_API_LEVEL 10 functions will be added here */ + int (*f_im_decode_exif)(i_img *im, unsigned char *data, size_t length); + + /* IMAGER_API_LEVEL 11 functions will be added here */ } im_ext_funcs; #define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table" diff --git a/lib/Imager/APIRef.pod b/lib/Imager/APIRef.pod index a912d1d7..d659641b 100644 --- a/lib/Imager/APIRef.pod +++ b/lib/Imager/APIRef.pod @@ -2554,6 +2554,25 @@ If reallocation of slot storage fails, returns false. =for comment From: File context.c +=item im_decode_exif + +im_decode_exif(im, data_base, data_size); + +The data from C for C bytes will be scanned for +EXIF data. + +Any data found will be used to set tags in the supplied image. + +The intent is that invalid EXIF data will simply fail to set tags, and +write to the log. In no case should this code exit when supplied +invalid data. + +Returns true if an EXIF header was seen. + + +=for comment +From: File imexif.c + =item im_errors(ctx) i_errmsg *errors = im_errors(aIMCTX); diff --git a/xt/x20spell.t b/xt/x20spell.t index 405f0e20..2084f9b8 100644 --- a/xt/x20spell.t +++ b/xt/x20spell.t @@ -21,6 +21,7 @@ Blit CGI CMYK CPAN +EXIF FreeType GDI GIF -- 2.39.5