add sniffing framework to magickload

though it only spots ICO for now

see https://github.com/jcupitt/pyvips/issues/39
This commit is contained in:
John Cupitt 2018-07-24 17:38:36 +01:00
parent 72f589764a
commit e89dac20bb
5 changed files with 72 additions and 21 deletions

View File

@ -35,6 +35,7 @@
- paste in the test suite from pyvips
- get EXIF tag names from tag plus ifd [@Nan619]
- escape ASCII control characters in XML
- magickload now sniffs some file types itself
12/3/18 started 8.6.4
- better fitting of fonts with overhanging edges [Adrià]

View File

@ -1,6 +1,9 @@
/* Common functions for interfacing with ImageMagick.
*
* 22/12/17 dlemstra
*
* 24/7/18
* - add the sniffer
*/
/*
@ -238,6 +241,46 @@ magick_set_image_option( ImageInfo *image_info,
#endif /*HAVE_SETIMAGEOPTION*/
}
/* ImageMagick can't detect some formats, like ICO, by examining the contents --
* ico.c simply does not have a recogniser.
*
* For these formats, do the detection ourselves.
*
* Set image_info->magick if we spot one of the things we can spot.
*/
static const char *
magick_sniff( const unsigned char *bytes, size_t length )
{
if( length >= 4 &&
bytes[0] == 0 &&
bytes[1] == 0 &&
bytes[2] == 1 &&
bytes[3] == 0 )
return( "ICO" );
return( NULL );
}
void
magick_sniff_bytes( ImageInfo *image_info,
const unsigned char *bytes, size_t length )
{
const char *format;
if( (format = magick_sniff( bytes, length )) )
vips_strncpy( image_info->magick, format, MaxTextExtent );
}
void
magick_sniff_file( ImageInfo *image_info, const char *filename )
{
unsigned char bytes[256];
size_t length;
if( (length = vips__get_bytes( filename, bytes, 256 )) >= 4 )
magick_sniff_bytes( image_info, bytes, 256 );
}
void
magick_vips_error( const char *domain, ExceptionInfo *exception )
{

View File

@ -59,6 +59,9 @@ void magick_set_number_scenes( ImageInfo *image_info,
int scene, int number_scenes );
void magick_inherit_exception( ExceptionInfo *exception, Image *image );
void magick_sniff_bytes( ImageInfo *image_info,
const unsigned char *bytes, size_t length );
void magick_sniff_file( ImageInfo *image_info, const char *filename );
void magick_vips_error( const char *domain, ExceptionInfo *exception );
void magick_genesis( void );

View File

@ -57,6 +57,8 @@
* - try using GetImageChannelDepth() instead of ->depth
* 25/5/18
* - don't use Ping, it's too unreliable
* 24/7/18
* - sniff extra filetypes
*/
/*
@ -128,6 +130,8 @@
typedef struct _Read {
char *filename;
VipsImage *im;
const void *buf;
size_t len;
int page;
int n;
@ -182,7 +186,8 @@ read_close( VipsImage *im, Read *read )
static Read *
read_new( const char *filename, VipsImage *im,
const char *density, int page, int n )
const void *buf, const size_t len,
const char *density, int page, int n )
{
Read *read;
@ -197,6 +202,8 @@ read_new( const char *filename, VipsImage *im,
if( !(read = VIPS_NEW( im, Read )) )
return( NULL );
read->filename = filename ? g_strdup( filename ) : NULL;
read->buf = buf;
read->len = len;
read->page = page;
read->n = n;
read->im = im;
@ -218,15 +225,12 @@ read_new( const char *filename, VipsImage *im,
vips_strncpy( read->image_info->filename,
filename, MaxTextExtent );
/* The file format hint, eg. "ICO".
*
if( format )
vips_strncpy( read->image_info->magick,
format, MaxTextExtent );
*
/* Any extra file format detection.
*/
printf( "magick2vips: insert format stuff here\n" );
if( filename )
magick_sniff_file( read->image_info, filename );
if( buf )
magick_sniff_bytes( read->image_info, buf, len );
/* Canvas resolution for rendering vector formats like SVG.
*/
@ -754,7 +758,7 @@ vips__magick_read( const char *filename,
printf( "magick2vips: vips__magick_read: %s\n", filename );
#endif /*DEBUG*/
if( !(read = read_new( filename, out, density, page, n )) )
if( !(read = read_new( filename, out, NULL, n, density, page, n )) )
return( -1 );
#ifdef DEBUG
@ -788,7 +792,7 @@ vips__magick_read_header( const char *filename,
printf( "vips__magick_read_header: %s\n", filename );
#endif /*DEBUG*/
if( !(read = read_new( filename, out, density, page, n )) )
if( !(read = read_new( filename, out, NULL, 0, density, page, n )) )
return( -1 );
#ifdef DEBUG
@ -833,7 +837,7 @@ vips__magick_read_buffer( const void *buf, const size_t len,
printf( "magick2vips: vips__magick_read_buffer: %p %zu\n", buf, len );
#endif /*DEBUG*/
if( !(read = read_new( NULL, out, density, page, n )) )
if( !(read = read_new( NULL, out, buf, len, density, page, n )) )
return( -1 );
#ifdef DEBUG
@ -867,7 +871,7 @@ vips__magick_read_buffer_header( const void *buf, const size_t len,
printf( "vips__magick_read_buffer_header: %p %zu\n", buf, len );
#endif /*DEBUG*/
if( !(read = read_new( NULL, out, density, page, n )) )
if( !(read = read_new( NULL, out, buf, len, density, page, n )) )
return( -1 );
#ifdef DEBUG

View File

@ -4,6 +4,8 @@
* - from magickload
* 25/11/16
* - add @n, deprecate @all_frames (just sets n = -1)
* 24/7/18
* - sniff extra filetypes
*/
/*
@ -305,14 +307,6 @@ vips_foreign_load_magick7_build( VipsObject *object )
if( magick7->all_frames )
magick7->n = -1;
/* The file format hint, eg. "ICO".
*
if( magick7->format )
vips_strncpy( magick7->image_info->magick,
magick7->format, MaxTextExtent );
*
*/
/* Canvas resolution for rendering vector formats like SVG.
*/
VIPS_SETSTR( magick7->image_info->density, magick7->density );
@ -768,6 +762,7 @@ ismagick7( const char *filename )
image_info = CloneImageInfo( NULL );
exception = AcquireExceptionInfo();
vips_strncpy( image_info->filename, filename, MagickPathExtent );
magick_sniff_file( image_info, filename );
image = PingImage( image_info, exception );
result = image != NULL;
VIPS_FREEF( DestroyImageList, image );
@ -790,6 +785,8 @@ vips_foreign_load_magick7_file_header( VipsForeignLoad *load )
vips_strncpy( magick7->image_info->filename, file->filename,
MagickPathExtent );
magick_sniff_file( magick7->image_info, file->filename );
/* It would be great if we could PingImage and just read the header,
* but sadly many IM coders do not support ping. The critical one for
* us is DICOM.
@ -867,6 +864,7 @@ vips_foreign_load_magick7_buffer_is_a_buffer( const void *buf, size_t len )
*/
image_info = CloneImageInfo( NULL );
exception = AcquireExceptionInfo();
magick_sniff_bytes( image_info, buf, len );
image = PingBlob( image_info, buf, len, exception );
result = image != NULL;
VIPS_FREEF( DestroyImageList, image );
@ -893,6 +891,8 @@ vips_foreign_load_magick7_buffer_header( VipsForeignLoad *load )
*
* We have to read the whole image in _header.
*/
magick_sniff_bytes( magick7->image_info,
magick7_buffer->buf->data, magick7_buffer->buf->length );
magick7->image = BlobToImage( magick7->image_info,
magick7_buffer->buf->data, magick7_buffer->buf->length,
magick7->exception );