Merge branch 'master' of github.com:jcupitt/libvips
This commit is contained in:
commit
0c7053bae1
@ -29,6 +29,13 @@
|
||||
- better upsizing with vips_resize()
|
||||
- added vips_worley(), generate Worley noise
|
||||
- added vips_perlin(), generate Perlin noise
|
||||
- gif loader can write 1, 2, 3, or 4 bands depending on file contents
|
||||
- support --strip for pngsave
|
||||
- add svgz support [Felix Bünemann]
|
||||
|
||||
30/7/16 started 8.3.3
|
||||
- fix performance regression in 8.3.2, thanks Lovell
|
||||
- yet more robust vips file reading
|
||||
|
||||
18/5/16 started 8.3.2
|
||||
- more robust vips image reading
|
||||
|
16
TODO
16
TODO
@ -1,14 +1,14 @@
|
||||
- try:
|
||||
|
||||
$ vips avg broken.jpg[fail]
|
||||
|
||||
about 50% of the time it'll trigger a range of out-of-order reads and lock
|
||||
for 10s or so while seq times out
|
||||
|
||||
- add more webp tests to py suite
|
||||
|
||||
- try moving some more of the CLI tests to py
|
||||
|
||||
- the gif tests in the suite sometimes fail with giflib5 because of an
|
||||
uninitialized struct in giflib, see
|
||||
|
||||
https://sourceforge.net/p/giflib/bugs/94/
|
||||
|
||||
sadly ubuntu 16.04 only comes with giflib5, and giflib5 is currently broken
|
||||
|
||||
- I like the new int mask creator in reducev, can we use it in im_vips2imask()
|
||||
as well?
|
||||
|
||||
@ -18,8 +18,6 @@
|
||||
|
||||
- could load pdf thumbnails?
|
||||
|
||||
- still not happy about float->int mask conversion in im_vips2mask.c
|
||||
|
||||
- colour needs to split _build() into preprocess / process / postprocess
|
||||
phases
|
||||
|
||||
|
41
configure.ac
41
configure.ac
@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date`
|
||||
# binary interface changes not backwards compatible?: reset age to 0
|
||||
|
||||
LIBRARY_CURRENT=46
|
||||
LIBRARY_REVISION=2
|
||||
LIBRARY_REVISION=3
|
||||
LIBRARY_AGE=4
|
||||
|
||||
# patched into include/vips/version.h
|
||||
@ -627,6 +627,29 @@ if test x"$with_rsvg" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
# zlib
|
||||
# some platforms, like macosx, are missing the .pc files for zlib, so
|
||||
# we fall back to FIND_ZLIB
|
||||
AC_ARG_WITH([zlib],
|
||||
AS_HELP_STRING([--without-zlib], [build without zlib (default: test)]))
|
||||
|
||||
if test x"$with_zlib" != "xno"; then
|
||||
PKG_CHECK_MODULES(ZLIB, zlib >= 0.4,
|
||||
[AC_DEFINE(HAVE_ZLIB,1,[define if you have zlib installed.])
|
||||
with_zlib=yes
|
||||
PACKAGES_USED="$PACKAGES_USED zlib"
|
||||
],
|
||||
[FIND_ZLIB(
|
||||
[with_zlib="yes (found by search)"
|
||||
],
|
||||
[AC_MSG_WARN([zlib not found; disabling SVGZ buffer support])
|
||||
with_zlib=no
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
fi
|
||||
|
||||
# OpenSlide
|
||||
AC_ARG_WITH([openslide],
|
||||
AS_HELP_STRING([--without-openslide],
|
||||
@ -787,15 +810,6 @@ fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_PYVIPS8, test x"$enable_pyvips8" = x"yes")
|
||||
|
||||
# hmm, these don't have .pc files on ubuntu 5.10, how odd
|
||||
FIND_ZIP(
|
||||
[with_zip=yes
|
||||
],
|
||||
[AC_MSG_WARN([libz not found; disabling ZIP support])
|
||||
with_zip=no
|
||||
]
|
||||
)
|
||||
|
||||
# look for TIFF with pkg-config ... fall back to our tester
|
||||
# pkgconfig support for libtiff starts with libtiff-4
|
||||
AC_ARG_WITH([tiff],
|
||||
@ -944,14 +958,14 @@ fi
|
||||
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
|
||||
# sort includes to get longer, more specific dirs first
|
||||
# helps, for example, selecting graphicsmagick over imagemagick
|
||||
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
|
||||
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $ZLIB_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
|
||||
do
|
||||
echo $i
|
||||
done | sort -ru`
|
||||
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
|
||||
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
|
||||
VIPS_INCLUDES="$PNG_INCLUDES $TIFF_INCLUDES $ZIP_INCLUDES $JPEG_INCLUDES"
|
||||
VIPS_LIBS="$MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $ZIP_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $GIFLIB_LIBS $RSVG_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
||||
VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES"
|
||||
VIPS_LIBS="$ZLIB_LIBS $MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $GIFLIB_LIBS $RSVG_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
||||
|
||||
AC_SUBST(VIPS_LIBDIR)
|
||||
|
||||
@ -1047,6 +1061,7 @@ PDF import with poppler-glib: $with_poppler
|
||||
(requires poppler-glib 0.16.0 or later)
|
||||
SVG import with librsvg-2.0: $with_rsvg
|
||||
(requires librsvg-2.0 2.34.0 or later)
|
||||
zlib: $with_zlib
|
||||
file import with cfitsio: $with_cfitsio
|
||||
file import/export with libwebp: $with_libwebp
|
||||
(requires libwebp-0.1.3 or later)
|
||||
|
@ -461,7 +461,7 @@ VImage::call_option_string( const char *operation_name,
|
||||
{
|
||||
VipsOperation *operation;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_call_by_name: starting for %s ...\n",
|
||||
VIPS_DEBUG_MSG( "call_option_string: starting for %s ...\n",
|
||||
operation_name );
|
||||
|
||||
if( !(operation = vips_operation_new( operation_name )) ) {
|
||||
@ -489,6 +489,7 @@ VImage::call_option_string( const char *operation_name,
|
||||
*/
|
||||
if( vips_cache_operation_buildp( &operation ) ) {
|
||||
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
|
||||
g_object_unref( operation );
|
||||
delete options;
|
||||
throw( VError() );
|
||||
}
|
||||
|
@ -703,11 +703,8 @@ vips_tile_cache_gen( VipsRegion *or,
|
||||
"error on tile %p\n", tile );
|
||||
|
||||
vips_warn( class->nickname,
|
||||
_( "error reading tile %dx%d: "
|
||||
"%s" ),
|
||||
tile->pos.left, tile->pos.top,
|
||||
vips_error_buffer() );
|
||||
vips_error_clear();
|
||||
_( "error in tile %d x %d" ),
|
||||
tile->pos.left, tile->pos.top );
|
||||
|
||||
vips_region_black( tile->region );
|
||||
|
||||
|
@ -341,11 +341,11 @@ vips_text_init( VipsText *text )
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @font: font to render with
|
||||
* * @width: render within this many pixels across
|
||||
* * @alignment: left/centre/right alignment
|
||||
* * @dpi: render at this resolution
|
||||
* * @spacing: space lines by this in points
|
||||
* * @font: %gchararray, font to render with
|
||||
* * @width: %gint, render within this many pixels across
|
||||
* * @align: #VipsAlign, left/centre/right alignment
|
||||
* * @dpi: %gint, render at this resolution
|
||||
* * @spacing: %gint, space lines by this in points
|
||||
*
|
||||
* Draw the string @text to an image. @out is a one-band 8-bit
|
||||
* unsigned char image, with 0 for no text and 255 for text. Values inbetween
|
||||
@ -359,7 +359,7 @@ vips_text_init( VipsText *text )
|
||||
*
|
||||
* @width is the maximum number of pixels across to draw within. If the
|
||||
* generated text is wider than this, it will wrap to a new line. In this
|
||||
* case, @alignment can be used to set the alignment style for multi-line
|
||||
* case, @align can be used to set the alignment style for multi-line
|
||||
* text.
|
||||
*
|
||||
* @dpi sets the resolution to render at. "sans 12" at 72 dpi draws characters
|
||||
|
@ -4,6 +4,9 @@
|
||||
* - from svgload.c
|
||||
* 25/4/16
|
||||
* - add giflib5 support
|
||||
* 26/7/16
|
||||
* - transparency was wrong if there was no EXTENSION_RECORD
|
||||
* - write 1, 2, 3, or 4 bands depending on file contents
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -86,6 +89,14 @@ typedef struct _VipsForeignLoadGif {
|
||||
*/
|
||||
GifPixelType *line;
|
||||
|
||||
/* We decompress the whole thing to a huge RGBA memory image, and
|
||||
* as we render, watch for bands and transparency. At the end of
|
||||
* loading, we copy 1 or 3 bands, with or without transparency to
|
||||
* output.
|
||||
*/
|
||||
gboolean has_transparency;
|
||||
gboolean has_colour;
|
||||
|
||||
} VipsForeignLoadGif;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadGifClass;
|
||||
@ -302,39 +313,11 @@ vips_foreign_load_gif_is_a( const char *filename )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_gif_parse( VipsForeignLoadGif *gif,
|
||||
VipsImage *out )
|
||||
{
|
||||
vips_image_init_fields( out,
|
||||
gif->file->SWidth, gif->file->SHeight,
|
||||
4, VIPS_FORMAT_UCHAR,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
|
||||
/* We will have the whole GIF frame in memory, so we can render any
|
||||
* area.
|
||||
*/
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
/* We need a line buffer to decompress to.
|
||||
*/
|
||||
gif->line = VIPS_ARRAY( gif, gif->file->SWidth, GifPixelType );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||
|
||||
vips_foreign_load_gif_parse( gif, load->out );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
||||
int width, VipsPel * restrict q, VipsPel * restrict p )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
ColorMapObject *map = gif->file->Image.ColorMap ?
|
||||
gif->file->Image.ColorMap : gif->file->SColorMap;
|
||||
|
||||
@ -343,8 +326,13 @@ vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
||||
for( x = 0; x < width; x++ ) {
|
||||
VipsPel v = p[x];
|
||||
|
||||
if( v != gif->transparency &&
|
||||
v < map->ColorCount ) {
|
||||
if( v >= map->ColorCount ) {
|
||||
vips_warn( class->nickname,
|
||||
"%s", _( "pixel value out of range" ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( v != gif->transparency ) {
|
||||
q[0] = map->Colors[v].Red;
|
||||
q[1] = map->Colors[v].Green;
|
||||
q[2] = map->Colors[v].Blue;
|
||||
@ -370,6 +358,8 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif, VipsImage *out )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
GifFileType *file = gif->file;
|
||||
ColorMapObject *map = file->Image.ColorMap ?
|
||||
file->Image.ColorMap : file->SColorMap;
|
||||
|
||||
/* Check that the frame lies within our image.
|
||||
*/
|
||||
@ -382,10 +372,27 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif, VipsImage *out )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Check if we have a non-greyscale colourmap for this frame.
|
||||
*/
|
||||
if( !gif->has_colour ) {
|
||||
int i;
|
||||
|
||||
for( i = 0; i < map->ColorCount; i++ )
|
||||
if( map->Colors[i].Red != map->Colors[i].Green ||
|
||||
map->Colors[i].Green != map->Colors[i].Blue ) {
|
||||
VIPS_DEBUG_MSG( "gifload: not mono\n" );
|
||||
gif->has_colour = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( file->Image.Interlace ) {
|
||||
int i;
|
||||
|
||||
VIPS_DEBUG_MSG( "gifload: interlaced frame\n" );
|
||||
VIPS_DEBUG_MSG( "gifload: interlaced frame of "
|
||||
"%d x %d pixels at %d x %d\n",
|
||||
file->Image.Width, file->Image.Height,
|
||||
file->Image.Left, file->Image.Top );
|
||||
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
int y;
|
||||
@ -410,6 +417,11 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif, VipsImage *out )
|
||||
else {
|
||||
int y;
|
||||
|
||||
VIPS_DEBUG_MSG( "gifload: non-interlaced frame of "
|
||||
"%d x %d pixels at %d x %d\n",
|
||||
file->Image.Width, file->Image.Height,
|
||||
file->Image.Left, file->Image.Top );
|
||||
|
||||
for( y = 0; y < file->Image.Height; y++ ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( out,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
@ -429,20 +441,31 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif, VipsImage *out )
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
vips_foreign_load_gif_to_memory( VipsForeignLoadGif *gif, VipsImage *out )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
|
||||
int frame_n;
|
||||
GifRecordType record;
|
||||
|
||||
vips_foreign_load_gif_parse( gif, load->real );
|
||||
vips_image_init_fields( out,
|
||||
gif->file->SWidth, gif->file->SHeight,
|
||||
4, VIPS_FORMAT_UCHAR,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
|
||||
/* We will have the whole GIF frame in memory, so we can render any
|
||||
* area.
|
||||
*/
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
/* We need a line buffer to decompress to.
|
||||
*/
|
||||
gif->line = VIPS_ARRAY( gif, gif->file->SWidth, GifPixelType );
|
||||
|
||||
/* Turn out into a memory image which we then render the GIF frames
|
||||
* into.
|
||||
*/
|
||||
if( vips_image_write_prepare( load->real ) )
|
||||
if( vips_image_write_prepare( out ) )
|
||||
return( -1 );
|
||||
|
||||
/* Scan the GIF until we have enough to have completely rendered the
|
||||
@ -467,7 +490,7 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_foreign_load_gif_render( gif, load->real ) )
|
||||
if( vips_foreign_load_gif_render( gif, out ) )
|
||||
return( -1 );
|
||||
|
||||
frame_n += 1;
|
||||
@ -495,6 +518,7 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
* transparency.
|
||||
*/
|
||||
gif->transparency = extension[4];
|
||||
gif->has_transparency = TRUE;
|
||||
|
||||
VIPS_DEBUG_MSG( "gifload: "
|
||||
"seen transparency %d\n",
|
||||
@ -549,6 +573,62 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( load ), 4 );
|
||||
|
||||
VipsImage *im;
|
||||
|
||||
/* Render to a memory image.
|
||||
*/
|
||||
im = t[0] = vips_image_new_memory();
|
||||
if( vips_foreign_load_gif_to_memory( gif, im ) )
|
||||
return( -1 );
|
||||
|
||||
/* Depending on what we found, transform and write to load->real.
|
||||
*/
|
||||
if( gif->has_colour &&
|
||||
gif->has_transparency ) {
|
||||
/* Nothing to do.
|
||||
*/
|
||||
}
|
||||
else if( gif->has_colour ) {
|
||||
/* RGB.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 0,
|
||||
"n", 3,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
im = t[1];
|
||||
}
|
||||
else if( gif->has_transparency ) {
|
||||
/* GA.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 0, NULL ) ||
|
||||
vips_extract_band( im, &t[2], 3, NULL ) ||
|
||||
vips_bandjoin2( t[1], t[2], &t[3], NULL ) )
|
||||
return( -1 );
|
||||
im = t[3];
|
||||
im->Type = VIPS_INTERPRETATION_B_W;
|
||||
}
|
||||
else {
|
||||
/* G.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 0, NULL ) )
|
||||
return( -1 );
|
||||
im = t[1];
|
||||
im->Type = VIPS_INTERPRETATION_B_W;
|
||||
}
|
||||
|
||||
if( vips_image_write( im, load->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_gif_class_init( VipsForeignLoadGifClass *class )
|
||||
{
|
||||
@ -566,7 +646,6 @@ vips_foreign_load_gif_class_init( VipsForeignLoadGifClass *class )
|
||||
load_class->get_flags_filename =
|
||||
vips_foreign_load_gif_get_flags_filename;
|
||||
load_class->get_flags = vips_foreign_load_gif_get_flags;
|
||||
load_class->load = vips_foreign_load_gif_load;
|
||||
|
||||
VIPS_ARG_INT( class, "page", 10,
|
||||
_( "Page" ),
|
||||
@ -580,6 +659,7 @@ vips_foreign_load_gif_class_init( VipsForeignLoadGifClass *class )
|
||||
static void
|
||||
vips_foreign_load_gif_init( VipsForeignLoadGif *gif )
|
||||
{
|
||||
gif->transparency = -1;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadGifFile {
|
||||
@ -607,7 +687,7 @@ vips_foreign_load_gif_file_header( VipsForeignLoad *load )
|
||||
|
||||
VIPS_SETSTR( load->out->filename, file->filename );
|
||||
|
||||
return( vips_foreign_load_gif_header( load ) );
|
||||
return( vips_foreign_load_gif_load( load ) );
|
||||
}
|
||||
|
||||
static const char *vips_foreign_gif_suffs[] = {
|
||||
@ -702,7 +782,7 @@ vips_foreign_load_gif_buffer_header( VipsForeignLoad *load )
|
||||
vips_foreign_load_gif_buffer_read ) )
|
||||
return( -1 );
|
||||
|
||||
return( vips_foreign_load_gif_header( load ) );
|
||||
return( vips_foreign_load_gif_load( load ) );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -752,8 +832,8 @@ vips_foreign_load_gif_buffer_init( VipsForeignLoadGifBuffer *buffer )
|
||||
*
|
||||
* Use @page to set page number (frame number) to read.
|
||||
*
|
||||
* The whole GIF is parsed and read into memory on header access, the whole
|
||||
* GIF is rendered on first pixel access.
|
||||
* The whole GIF is rendered into memory on header access. The output image
|
||||
* will be 1, 2, 3 or 4 bands depending on what the reader finds in the file.
|
||||
*
|
||||
* See also: vips_image_new_from_file().
|
||||
*
|
||||
|
@ -977,27 +977,29 @@ read_jpeg_generate( VipsRegion *or,
|
||||
* a vips_sequential().
|
||||
*/
|
||||
if( r->top != jpeg->y_pos ) {
|
||||
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
||||
vips_error( "VipsJpeg",
|
||||
_( "out of order read at line %d" ), jpeg->y_pos );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Here for longjmp() from vips__new_error_exit().
|
||||
*/
|
||||
if( setjmp( jpeg->eman.jmp ) )
|
||||
if( setjmp( jpeg->eman.jmp ) ) {
|
||||
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* If --fail is set, we make read fail on any warnings. This will stop
|
||||
* on any errors from the previous jpeg_read_scanlines().
|
||||
*/
|
||||
if( jpeg->eman.pub.num_warnings > 0 &&
|
||||
jpeg->fail ) {
|
||||
vips_error( "VipsJpeg",
|
||||
_( "read gave %ld warnings" ),
|
||||
jpeg->eman.pub.num_warnings );
|
||||
vips_error( NULL, "%s", vips_error_buffer() );
|
||||
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
||||
|
||||
/* Make the message only appear once.
|
||||
/* Only fail once.
|
||||
*/
|
||||
jpeg->eman.pub.num_warnings = 0;
|
||||
|
||||
|
@ -164,8 +164,9 @@ vips_foreign_save_png_file_build( VipsObject *object )
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write( save->ready, png_file->filename,
|
||||
png->compression, png->interlace, png->profile, png->filter ) )
|
||||
if( vips__png_write( save->ready,
|
||||
png_file->filename, png->compression, png->interlace,
|
||||
png->profile, png->filter, save->strip ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -223,7 +224,8 @@ vips_foreign_save_png_buffer_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__png_write_buf( save->ready, &obuf, &olen,
|
||||
png->compression, png->interlace, png->profile, png->filter ) )
|
||||
png->compression, png->interlace, png->profile, png->filter,
|
||||
save->strip ) )
|
||||
return( -1 );
|
||||
|
||||
/* vips__png_write_buf() makes a buffer that needs g_free(), not
|
||||
|
@ -2,6 +2,8 @@
|
||||
*
|
||||
* 7/2/16
|
||||
* - from svgload.c
|
||||
* 1/8/16 felixbuenemann
|
||||
* - add svgz support
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -55,6 +57,23 @@
|
||||
#include <cairo.h>
|
||||
#include <librsvg/rsvg.h>
|
||||
|
||||
/* Old librsvg versions don't include librsvg-features.h by default.
|
||||
* Newer versions deprecate direct inclusion.
|
||||
*/
|
||||
#ifndef LIBRSVG_FEATURES_H
|
||||
#include <librsvg/librsvg-features.h>
|
||||
#endif
|
||||
|
||||
/* A handy #define for we-will-handle-svgz.
|
||||
*/
|
||||
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB)
|
||||
#define HANDLE_SVGZ
|
||||
#endif
|
||||
|
||||
#ifdef HANDLE_SVGZ
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
typedef struct _VipsForeignLoadSvg {
|
||||
VipsForeignLoad parent_object;
|
||||
|
||||
@ -315,6 +334,12 @@ vips_foreign_load_svg_file_header( VipsForeignLoad *load )
|
||||
|
||||
static const char *vips_foreign_svg_suffs[] = {
|
||||
".svg",
|
||||
/* librsvg supports svgz directly, no need to check for zlib here.
|
||||
*/
|
||||
#if LIBRSVG_CHECK_FEATURE(SVGZ)
|
||||
".svgz",
|
||||
".svg.gz",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -364,13 +389,78 @@ typedef VipsForeignLoadSvgClass VipsForeignLoadSvgBufferClass;
|
||||
G_DEFINE_TYPE( VipsForeignLoadSvgBuffer, vips_foreign_load_svg_buffer,
|
||||
vips_foreign_load_svg_get_type() );
|
||||
|
||||
#ifdef HANDLE_SVGZ
|
||||
static void *
|
||||
vips_foreign_load_svg_zalloc( void *opaque, unsigned items, unsigned size )
|
||||
{
|
||||
return( g_malloc0_n( items, size ) );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_svg_zfree( void *opaque, void *ptr )
|
||||
{
|
||||
return( g_free( ptr ) );
|
||||
}
|
||||
#endif /*HANDLE_SVGZ*/
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_svg_is_a_buffer( const void *buf, size_t len )
|
||||
{
|
||||
char *str = (char *) buf;
|
||||
char *str;
|
||||
|
||||
#ifdef HANDLE_SVGZ
|
||||
/* If the buffer looks like a zip, deflate to here and then search
|
||||
* that for <svg.
|
||||
*/
|
||||
char obuf[224];
|
||||
#endif /*HANDLE_SVGZ*/
|
||||
|
||||
int i;
|
||||
|
||||
/* Start with str pointing at the argument buffer, swap to it pointing
|
||||
* into obuf if we see zip data.
|
||||
*/
|
||||
str = (char *) buf;
|
||||
|
||||
#ifdef HANDLE_SVGZ
|
||||
/* Check for SVGZ gzip signature and inflate.
|
||||
*
|
||||
* Minimum gzip size is 18 bytes, starting with 1F 8B.
|
||||
*/
|
||||
if( len >= 18 &&
|
||||
str[0] == '\037' &&
|
||||
str[1] == '\213' ) {
|
||||
z_stream zs;
|
||||
size_t opos;
|
||||
|
||||
zs.zalloc = (alloc_func) vips_foreign_load_svg_zalloc;
|
||||
zs.zfree = (free_func) vips_foreign_load_svg_zfree;
|
||||
zs.opaque = Z_NULL;
|
||||
zs.next_in = (unsigned char *) str;
|
||||
zs.avail_in = len;
|
||||
|
||||
/* There isn't really an error return from is_a_buffer()
|
||||
*/
|
||||
if( inflateInit2( &zs, 15 | 32 ) != Z_OK )
|
||||
return( FALSE );
|
||||
|
||||
opos = 0;
|
||||
do {
|
||||
zs.avail_out = sizeof( obuf ) - opos;
|
||||
zs.next_out = (unsigned char *) obuf + opos;
|
||||
if( inflate( &zs, Z_NO_FLUSH ) < Z_OK )
|
||||
return( FALSE );
|
||||
opos = sizeof( obuf ) - zs.avail_out;
|
||||
} while( opos < sizeof( obuf ) &&
|
||||
zs.avail_in > 0 );
|
||||
|
||||
inflateEnd( &zs );
|
||||
|
||||
str = obuf;
|
||||
len = opos;
|
||||
}
|
||||
#endif /*HANDLE_SVGZ*/
|
||||
|
||||
/* SVG documents are very freeform. They normally look like:
|
||||
*
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
@ -390,19 +480,13 @@ vips_foreign_load_svg_is_a_buffer( const void *buf, size_t len )
|
||||
return( 0 );
|
||||
for( i = 0; i < 24; i++ )
|
||||
if( !isascii( str[i] ) )
|
||||
return( 0 );
|
||||
return( FALSE );
|
||||
|
||||
for( i = 0; i < 200 && i < len - 5; i++ ) {
|
||||
char txt[5];
|
||||
for( i = 0; i < 200 && i < len - 5; i++ )
|
||||
if( g_ascii_strncasecmp( str + i, "<svg", 4 ) == 0 )
|
||||
return( TRUE );
|
||||
|
||||
/* 5, since we include the \0 at the end.
|
||||
*/
|
||||
vips_strncpy( txt, buf + i, 5 );
|
||||
if( strcasecmp( txt, "<svg" ) == 0 )
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -55,6 +55,9 @@
|
||||
* 26/2/15
|
||||
* - close the read down early for a header read ... this saves an
|
||||
* fd during file read, handy for large numbers of input images
|
||||
* 31/7/16
|
||||
* - support --strip option
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -808,8 +811,9 @@ write_png_block( VipsRegion *region, VipsRect *area, void *a )
|
||||
/* Write a VIPS image to PNG.
|
||||
*/
|
||||
static int
|
||||
write_vips( Write *write, int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter )
|
||||
write_vips( Write *write,
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter, gboolean strip )
|
||||
{
|
||||
VipsImage *in = write->in;
|
||||
|
||||
@ -883,7 +887,8 @@ write_vips( Write *write, int compress, int interlace, const char *profile,
|
||||
|
||||
/* Set ICC Profile.
|
||||
*/
|
||||
if( profile ) {
|
||||
if( profile &&
|
||||
!strip ) {
|
||||
if( strcmp( profile, "none" ) != 0 ) {
|
||||
void *data;
|
||||
size_t length;
|
||||
@ -902,7 +907,8 @@ write_vips( Write *write, int compress, int interlace, const char *profile,
|
||||
PNG_COMPRESSION_TYPE_BASE, data, length );
|
||||
}
|
||||
}
|
||||
else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
|
||||
else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) &&
|
||||
!strip ) {
|
||||
void *data;
|
||||
size_t length;
|
||||
|
||||
@ -951,7 +957,7 @@ write_vips( Write *write, int compress, int interlace, const char *profile,
|
||||
int
|
||||
vips__png_write( VipsImage *in, const char *filename,
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter )
|
||||
VipsForeignPngFilter filter, gboolean strip )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -970,7 +976,8 @@ vips__png_write( VipsImage *in, const char *filename,
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write, compress, interlace, profile, filter ) ) {
|
||||
if( write_vips( write,
|
||||
compress, interlace, profile, filter, strip ) ) {
|
||||
vips_error( "vips2png",
|
||||
_( "unable to write \"%s\"" ), filename );
|
||||
|
||||
@ -1026,7 +1033,7 @@ user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
|
||||
int
|
||||
vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
const char *profile, VipsForeignPngFilter filter )
|
||||
const char *profile, VipsForeignPngFilter filter, gboolean strip )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -1037,7 +1044,8 @@ vips__png_write_buf( VipsImage *in,
|
||||
|
||||
/* Convert it!
|
||||
*/
|
||||
if( write_vips( write, compression, interlace, profile, filter ) ) {
|
||||
if( write_vips( write,
|
||||
compression, interlace, profile, filter, strip ) ) {
|
||||
vips_error( "vips2png",
|
||||
"%s", _( "unable to write to buffer" ) );
|
||||
|
||||
|
@ -48,10 +48,10 @@ int vips__png_header_buffer( const void *buffer, size_t length,
|
||||
|
||||
int vips__png_write( VipsImage *in, const char *filename,
|
||||
int compress, int interlace, const char *profile,
|
||||
VipsForeignPngFilter filter );
|
||||
VipsForeignPngFilter filter, gboolean strip );
|
||||
int vips__png_write_buf( VipsImage *in,
|
||||
void **obuf, size_t *olen, int compression, int interlace,
|
||||
const char *profile, VipsForeignPngFilter filter );
|
||||
const char *profile, VipsForeignPngFilter filter, gboolean strip );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -134,6 +134,7 @@ extern "C" {
|
||||
#define VIPS_META_ORIENTATION "orientation"
|
||||
|
||||
guint64 vips_format_sizeof( VipsBandFormat format );
|
||||
guint64 vips_format_sizeof_unsafe( VipsBandFormat format );
|
||||
|
||||
int vips_image_get_width( const VipsImage *image );
|
||||
int vips_image_get_height( const VipsImage *image );
|
||||
|
@ -363,10 +363,11 @@ GType vips_image_get_type(void);
|
||||
/* Has to be guint64 and not size_t/off_t since we have to be able to address
|
||||
* huge images on platforms with 32-bit files.
|
||||
*/
|
||||
|
||||
/* Pixel address calculation macros.
|
||||
*/
|
||||
#define VIPS_IMAGE_SIZEOF_ELEMENT( I ) \
|
||||
(vips_format_sizeof((I)->BandFmt))
|
||||
(vips_format_sizeof_unsafe((I)->BandFmt))
|
||||
#define VIPS_IMAGE_SIZEOF_PEL( I ) \
|
||||
(VIPS_IMAGE_SIZEOF_ELEMENT( I ) * (I)->Bands)
|
||||
#define VIPS_IMAGE_SIZEOF_LINE( I ) \
|
||||
|
@ -207,6 +207,7 @@ void *vips_hash_table_map( GHashTable *hash,
|
||||
char *vips_strncpy( char *dest, const char *src, int n );
|
||||
char *vips_strrstr( const char *haystack, const char *needle );
|
||||
gboolean vips_ispostfix( const char *a, const char *b );
|
||||
gboolean vips_iscasepostfix( const char *a, const char *b );
|
||||
gboolean vips_isprefix( const char *a, const char *b );
|
||||
char *vips_break_token( char *str, const char *brk );
|
||||
|
||||
|
@ -201,6 +201,23 @@ vips_format_sizeof( VipsBandFormat format )
|
||||
return( vips__image_sizeof_bandformat[format] );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_format_sizeof_unsafe: (skip)
|
||||
* @format: format type
|
||||
*
|
||||
* A fast but dangerous version of vips_format_sizeof(). You must have
|
||||
* previously range-checked @format or you'll crash.
|
||||
*
|
||||
* Returns: number of bytes for a band format.
|
||||
*/
|
||||
guint64
|
||||
vips_format_sizeof_unsafe( VipsBandFormat format )
|
||||
{
|
||||
g_assert( 0 <= format && format <= VIPS_FORMAT_DPCOMPLEX );
|
||||
|
||||
return( vips__image_sizeof_bandformat[format] );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Check that this meta is on the hash table.
|
||||
*/
|
||||
|
@ -231,9 +231,12 @@ vips__region_start( VipsRegion *region )
|
||||
g_mutex_unlock( image->sslock );
|
||||
|
||||
if( !region->seq ) {
|
||||
vips_error( "vips__region_start",
|
||||
_( "start function failed for image %s" ),
|
||||
#ifdef DEBUG
|
||||
printf( "vips__region_start: "
|
||||
"start function failed for image %s",
|
||||
image->filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
@ -890,7 +893,7 @@ vips_region_fill( VipsRegion *reg, VipsRect *r, VipsRegionFillFn fn, void *a )
|
||||
* the pixels we need. If it does, we could copy them and only
|
||||
* generate the new ones.
|
||||
*
|
||||
* However, we usually have neighboring regions on different threads,
|
||||
* However, we usually have neighbouring regions on different threads,
|
||||
* so from the point of view of this thread, we will get no overlaps
|
||||
* on successive prepare requests.
|
||||
*/
|
||||
|
@ -319,6 +319,20 @@ vips_ispostfix( const char *a, const char *b )
|
||||
return( strcmp( a + m - n, b ) == 0 );
|
||||
}
|
||||
|
||||
/* Case-insensitive test for string b ends string a. ASCII strings only.
|
||||
*/
|
||||
gboolean
|
||||
vips_iscasepostfix( const char *a, const char *b )
|
||||
{
|
||||
int m = strlen( a );
|
||||
int n = strlen( b );
|
||||
|
||||
if( n > m )
|
||||
return( FALSE );
|
||||
|
||||
return( strcasecmp( a + m - n, b ) == 0 );
|
||||
}
|
||||
|
||||
/* Test for string a starts string b. a is a known-good string, b may be
|
||||
* random data.
|
||||
*/
|
||||
@ -461,30 +475,22 @@ int
|
||||
vips_filename_suffix_match( const char *path, const char *suffixes[] )
|
||||
{
|
||||
char *basename;
|
||||
char *suffix;
|
||||
char *q;
|
||||
const char **p;
|
||||
int result;
|
||||
const char **p;
|
||||
|
||||
/* Drop any directory components, we want ignore any '.' in there.
|
||||
/* Drop any directory components.
|
||||
*/
|
||||
basename = g_path_get_basename( path );
|
||||
|
||||
/* Zap any trailing options.
|
||||
/* Zap any trailing [] options.
|
||||
*/
|
||||
if( (q = (char *) vips__find_rightmost_brackets( basename )) )
|
||||
*q = '\0';
|
||||
|
||||
/* And select just the '.' and to the right.
|
||||
*/
|
||||
if( (q = strrchr( basename, '.' )) )
|
||||
suffix = q;
|
||||
else
|
||||
suffix = basename;
|
||||
|
||||
result = 0;
|
||||
for( p = suffixes; *p; p++ )
|
||||
if( g_ascii_strcasecmp( suffix, *p ) == 0 ) {
|
||||
for( p = suffixes; *p; p++ )
|
||||
if( vips_iscasepostfix( basename, *p ) ) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Read and write a vips file
|
||||
/* Read and write a vips file.
|
||||
*
|
||||
* 22/5/08
|
||||
* - from im_open.c, im_openin.c, im_desc_hd.c, im_readhist.c,
|
||||
@ -330,6 +330,18 @@ vips__read_header_bytes( VipsImage *im, unsigned char *from )
|
||||
im->Xres = im->Xres_float;
|
||||
im->Yres = im->Yres_float;
|
||||
|
||||
/* Some protection against malicious files. We also check predicted
|
||||
* (based on these values) against real file length, see below.
|
||||
*/
|
||||
im->Xsize = VIPS_CLIP( 1, im->Xsize, VIPS_MAX_COORD );
|
||||
im->Ysize = VIPS_CLIP( 1, im->Ysize, VIPS_MAX_COORD );
|
||||
im->Bands = VIPS_CLIP( 1, im->Bands, VIPS_MAX_COORD );
|
||||
im->BandFmt = VIPS_CLIP( 0, im->BandFmt, VIPS_FORMAT_LAST - 1 );
|
||||
|
||||
/* Type, Coding, Offset, Res, etc. don't affect vips file layout, just
|
||||
* pixel interpretation, don't clip them.
|
||||
*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -321,15 +321,30 @@ vips_reduceh_gen( VipsRegion *out_region, void *seq,
|
||||
VIPS_GATE_START( "vips_reduceh_gen: work" );
|
||||
|
||||
for( int y = 0; y < r->height; y ++ ) {
|
||||
VipsPel *p0;
|
||||
VipsPel *q;
|
||||
|
||||
double X;
|
||||
|
||||
q = VIPS_REGION_ADDR( out_region, r->left, r->top + y );
|
||||
|
||||
X = r->left * reduceh->xshrink;
|
||||
|
||||
/* We want p0 to be the start (ie. x == 0) of the input
|
||||
* scanline we are reading from. We can then calculate the p we
|
||||
* need for each pixel with a single mul and avoid calling ADDR
|
||||
* for each pixel.
|
||||
*
|
||||
* We can't get p0 directly with ADDR since it could be outside
|
||||
* valid, so get the leftmost pixel in valid and subtract a
|
||||
* bit.
|
||||
*/
|
||||
p0 = VIPS_REGION_ADDR( ir, ir->valid.left, r->top + y ) -
|
||||
ir->valid.left * ps;
|
||||
|
||||
for( int x = 0; x < r->width; x++ ) {
|
||||
int ix = (int) X;
|
||||
VipsPel *p = VIPS_REGION_ADDR( ir, ix, r->top + y );
|
||||
VipsPel *p = p0 + ix * ps;
|
||||
const int sx = X * VIPS_TRANSFORM_SCALE * 2;
|
||||
const int six = sx & (VIPS_TRANSFORM_SCALE * 2 - 1);
|
||||
const int tx = (six + 1) >> 1;
|
||||
|
117
m4/zip.m4
117
m4/zip.m4
@ -1,117 +0,0 @@
|
||||
dnl From FIND_MOTIF and ACX_PTHREAD, without much understanding
|
||||
dnl
|
||||
dnl FIND_ZIP[ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]
|
||||
dnl ------------------------------------------------
|
||||
dnl
|
||||
dnl Find ZIP libraries and headers
|
||||
dnl
|
||||
dnl Put includes stuff in ZIP_INCLUDES
|
||||
dnl Put link stuff in ZIP_LIBS
|
||||
dnl Define HAVE_ZIP if found
|
||||
dnl
|
||||
AC_DEFUN([FIND_ZIP], [
|
||||
AC_REQUIRE([AC_PATH_XTRA])
|
||||
|
||||
ZIP_INCLUDES=""
|
||||
ZIP_LIBS=""
|
||||
|
||||
AC_ARG_WITH(zip,
|
||||
AS_HELP_STRING([--without-zip], [build without libx (default: test)]))
|
||||
# Treat --without-zip like --without-zip-includes --without-zip-libraries.
|
||||
if test "$with_zip" = "no"; then
|
||||
ZIP_INCLUDES=no
|
||||
ZIP_LIBS=no
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(zip-includes,
|
||||
AS_HELP_STRING([--with-zip-includes=DIR], [libz includes are in DIR]),
|
||||
ZIP_INCLUDES="-I$withval")
|
||||
AC_ARG_WITH(zip-libraries,
|
||||
AS_HELP_STRING([--with-zip-libraries=DIR], [libz libraries are in DIR]),
|
||||
ZIP_LIBS="-L$withval -lz")
|
||||
|
||||
AC_MSG_CHECKING(for ZIP)
|
||||
|
||||
# Look for zlib.h
|
||||
if test "$ZIP_INCLUDES" = ""; then
|
||||
# Check the standard search path
|
||||
AC_TRY_COMPILE([#include <zlib.h>],[int a;],[
|
||||
ZIP_INCLUDES=""
|
||||
], [
|
||||
# zlib.h is not in the standard search path, try
|
||||
# $prefix
|
||||
zip_save_INCLUDES="$INCLUDES"
|
||||
|
||||
INCLUDES="-I${prefix}/include $INCLUDES"
|
||||
|
||||
AC_TRY_COMPILE([#include <zlib.h>],[int a;],[
|
||||
ZIP_INCLUDES="-I${prefix}/include"
|
||||
], [
|
||||
ZIP_INCLUDES="no"
|
||||
])
|
||||
|
||||
INCLUDES=$zip_save_INCLUDES
|
||||
])
|
||||
fi
|
||||
|
||||
# Now for the libraries
|
||||
if test "$ZIP_LIBS" = ""; then
|
||||
zip_save_LIBS="$LIBS"
|
||||
zip_save_INCLUDES="$INCLUDES"
|
||||
|
||||
LIBS="-lz $LIBS"
|
||||
INCLUDES="$ZIP_INCLUDES $INCLUDES"
|
||||
|
||||
# Try the standard search path first
|
||||
AC_TRY_LINK([#include <zlib.h>],[zlibVersion()], [
|
||||
ZIP_LIBS="-lz"
|
||||
], [
|
||||
# libz is not in the standard search path, try $prefix
|
||||
|
||||
LIBS="-L${prefix}/lib $LIBS"
|
||||
|
||||
AC_TRY_LINK([#include <zlib.h>],[zlibVersion()], [
|
||||
ZIP_LIBS="-L${prefix}/lib -lz"
|
||||
], [
|
||||
ZIP_LIBS=no
|
||||
])
|
||||
])
|
||||
|
||||
LIBS="$zip_save_LIBS"
|
||||
INCLUDES="$zip_save_INCLUDES"
|
||||
fi
|
||||
|
||||
AC_SUBST(ZIP_LIBS)
|
||||
AC_SUBST(ZIP_INCLUDES)
|
||||
|
||||
# Print a helpful message
|
||||
zip_libraries_result="$ZIP_LIBS"
|
||||
zip_includes_result="$ZIP_INCLUDES"
|
||||
|
||||
if test x"$zip_libraries_result" = x""; then
|
||||
zip_libraries_result="in default path"
|
||||
fi
|
||||
if test x"$zip_includes_result" = x""; then
|
||||
zip_includes_result="in default path"
|
||||
fi
|
||||
|
||||
if test "$zip_libraries_result" = "no"; then
|
||||
zip_libraries_result="(none)"
|
||||
fi
|
||||
if test "$zip_includes_result" = "no"; then
|
||||
zip_includes_result="(none)"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([libraries $zip_libraries_result, headers $zip_includes_result])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test "$ZIP_INCLUDES" != "no" && test "$ZIP_LIBS" != "no"; then
|
||||
AC_DEFINE(HAVE_ZIP,1,[Define if you have libz libraries and header files.])
|
||||
$1
|
||||
else
|
||||
ZIP_LIBS=""
|
||||
ZIP_INCLUDES=""
|
||||
$2
|
||||
fi
|
||||
|
||||
])dnl
|
124
m4/zlib.m4
Normal file
124
m4/zlib.m4
Normal file
@ -0,0 +1,124 @@
|
||||
dnl From FIND_MOTIF and ACX_PTHREAD, without much understanding
|
||||
dnl
|
||||
dnl FIND_ZLIB[ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]
|
||||
dnl ------------------------------------------------
|
||||
dnl
|
||||
dnl Find zlib libraries and headers ... useful for platforms which are missing
|
||||
dnl the zlib .pc file
|
||||
dnl
|
||||
dnl Put compile stuff in ZLIB_INCLUDES
|
||||
dnl Put link stuff in ZLIB_LIBS
|
||||
dnl Define HAVE_ZLIB if found
|
||||
dnl
|
||||
AC_DEFUN([FIND_ZLIB], [
|
||||
AC_REQUIRE([AC_PATH_XTRA])
|
||||
|
||||
ZLIB_INCLUDES=""
|
||||
ZLIB_LIBS=""
|
||||
|
||||
AC_ARG_WITH(zlib,
|
||||
AS_HELP_STRING([--without-zlib], [build without zlib (default: test)]))
|
||||
# Treat --without-zlib like --without-zlib-includes --without-zlib-libraries.
|
||||
if test "$with_zlib" = "no"; then
|
||||
ZLIB_INCLUDES=no
|
||||
ZLIB_LIBS=no
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(zlib-includes,
|
||||
AS_HELP_STRING([--with-zlib-includes=DIR], [libz includes are in DIR]),
|
||||
ZLIB_INCLUDES="-I$withval")
|
||||
AC_ARG_WITH(zlib-libraries,
|
||||
AS_HELP_STRING([--with-zlib-libraries=DIR], [libz libraries are in DIR]),
|
||||
ZLIB_LIBS="-L$withval -lz")
|
||||
|
||||
AC_MSG_CHECKING(for ZLIB)
|
||||
|
||||
# Look for zlib.h
|
||||
if test "$ZLIB_INCLUDES" = ""; then
|
||||
# Check the standard search path
|
||||
AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <zlib.h>],[int a;],[
|
||||
ZLIB_INCLUDES=""
|
||||
], [
|
||||
# zlib.h is not in the standard search path, try
|
||||
# $prefix
|
||||
zlib_save_INCLUDES="$INCLUDES"
|
||||
|
||||
INCLUDES="-I${prefix}/include $INCLUDES"
|
||||
|
||||
AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <zlib.h>],[int a;],[
|
||||
ZLIB_INCLUDES="-I${prefix}/include"
|
||||
], [
|
||||
ZLIB_INCLUDES="no"
|
||||
])
|
||||
|
||||
INCLUDES=$zlib_save_INCLUDES
|
||||
])
|
||||
fi
|
||||
|
||||
# Now for the libraries
|
||||
if test "$ZLIB_LIBS" = ""; then
|
||||
zlib_save_LIBS="$LIBS"
|
||||
zlib_save_INCLUDES="$INCLUDES"
|
||||
|
||||
LIBS="-lz $LIBS"
|
||||
INCLUDES="$ZLIB_INCLUDES $INCLUDES"
|
||||
|
||||
# Try the standard search path first
|
||||
AC_TRY_LINK([#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
],[z_stream zs;inflateInit2(&zs, 15 | 32)], [
|
||||
ZLIB_LIBS="-lz"
|
||||
], [
|
||||
# libz is not in the standard search path, try $prefix
|
||||
|
||||
LIBS="-L${prefix}/lib $LIBS"
|
||||
|
||||
AC_TRY_LINK([#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
],[z_stream zs;inflateInit2(&zs, 15 | 32)], [
|
||||
ZLIB_LIBS="-L${prefix}/lib -lz"
|
||||
], [
|
||||
ZLIB_LIBS=no
|
||||
])
|
||||
])
|
||||
|
||||
LIBS="$zlib_save_LIBS"
|
||||
INCLUDES="$zlib_save_INCLUDES"
|
||||
fi
|
||||
|
||||
AC_SUBST(ZLIB_LIBS)
|
||||
AC_SUBST(ZLIB_INCLUDES)
|
||||
|
||||
# Print a helpful message
|
||||
zlib_libraries_result="$ZLIB_LIBS"
|
||||
zlib_includes_result="$ZLIB_INCLUDES"
|
||||
|
||||
if test x"$zlib_libraries_result" = x""; then
|
||||
zlib_libraries_result="in default path"
|
||||
fi
|
||||
if test x"$zlib_includes_result" = x""; then
|
||||
zlib_includes_result="in default path"
|
||||
fi
|
||||
|
||||
if test "$zlib_libraries_result" = "no"; then
|
||||
zlib_libraries_result="(none)"
|
||||
fi
|
||||
if test "$zlib_includes_result" = "no"; then
|
||||
zlib_includes_result="(none)"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([libraries $zlib_libraries_result, headers $zlib_includes_result])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test "$ZLIB_INCLUDES" != "no" && test "$ZLIB_LIBS" != "no"; then
|
||||
AC_DEFINE(HAVE_ZLIB,1,[Define if you have zlib libraries and header files.])
|
||||
$1
|
||||
else
|
||||
ZLIB_INCLUDES=""
|
||||
ZLIB_LIBS=""
|
||||
$2
|
||||
fi
|
||||
|
||||
])dnl
|
@ -176,7 +176,7 @@ class Error(Exception):
|
||||
"""
|
||||
def __init__(self, message, detail = None):
|
||||
self.message = message
|
||||
if detail == None:
|
||||
if detail == None or detail == "":
|
||||
detail = Vips.error_buffer()
|
||||
Vips.error_clear()
|
||||
self.detail = detail
|
||||
|
BIN
test/images/vips-profile.svg.gz
Normal file
BIN
test/images/vips-profile.svg.gz
Normal file
Binary file not shown.
BIN
test/images/vips-profile.svgz
Normal file
BIN
test/images/vips-profile.svgz
Normal file
Binary file not shown.
@ -50,6 +50,8 @@ class TestForeign(unittest.TestCase):
|
||||
self.pdf_file = "images/ISO_12233-reschart.pdf"
|
||||
self.cmyk_pdf_file = "images/cmyktest.pdf"
|
||||
self.svg_file = "images/vips-profile.svg"
|
||||
self.svgz_file = "images/vips-profile.svgz"
|
||||
self.svg_gz_file = "images/vips-profile.svg.gz"
|
||||
|
||||
self.colour = Vips.Image.jpegload(self.jpeg_file)
|
||||
self.mono = self.colour.extract_band(1)
|
||||
@ -58,9 +60,7 @@ class TestForeign(unittest.TestCase):
|
||||
self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK)
|
||||
|
||||
im = Vips.Image.new_from_file(self.gif_file)
|
||||
# some libMagick will load this mono image as RGB, some as mono ... test
|
||||
# band 0 to be safe
|
||||
self.onebit = im[0] > 128
|
||||
self.onebit = im > 128
|
||||
|
||||
# we have test files for formats which have a clear standard
|
||||
def file_loader(self, loader, test_file, validate):
|
||||
@ -475,10 +475,10 @@ class TestForeign(unittest.TestCase):
|
||||
|
||||
def gif_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [33, 33, 33, 255])
|
||||
self.assertAlmostEqualObjects(a, [33])
|
||||
self.assertEqual(im.width, 159)
|
||||
self.assertEqual(im.height, 203)
|
||||
self.assertEqual(im.bands, 4)
|
||||
self.assertEqual(im.bands, 1)
|
||||
|
||||
self.file_loader("gifload", self.gif_file, gif_valid)
|
||||
self.buffer_loader("gifload_buffer", self.gif_file, gif_valid)
|
||||
@ -499,6 +499,11 @@ class TestForeign(unittest.TestCase):
|
||||
self.file_loader("svgload", self.svg_file, svg_valid)
|
||||
self.buffer_loader("svgload_buffer", self.svg_file, svg_valid)
|
||||
|
||||
self.file_loader("svgload", self.svgz_file, svg_valid)
|
||||
self.buffer_loader("svgload_buffer", self.svgz_file, svg_valid)
|
||||
|
||||
self.file_loader("svgload", self.svg_gz_file, svg_valid)
|
||||
|
||||
im = Vips.Image.new_from_file(self.svg_file)
|
||||
x = Vips.Image.new_from_file(self.svg_file, scale = 2)
|
||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||
|
@ -81,6 +81,8 @@
|
||||
* - restore BandFmt after unpremultiply
|
||||
* 23/5/16
|
||||
* - no need to guess max-alpha now premultiply does this for us
|
||||
* 1/8/16
|
||||
* - use scRGB as the working space in linear mode
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -357,7 +359,7 @@ thumbnail_shrink( VipsObject *process, VipsImage *in )
|
||||
{
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( process, 10 );
|
||||
VipsInterpretation interpretation = linear_processing ?
|
||||
VIPS_INTERPRETATION_XYZ : VIPS_INTERPRETATION_sRGB;
|
||||
VIPS_INTERPRETATION_scRGB : VIPS_INTERPRETATION_sRGB;
|
||||
|
||||
/* TRUE if we've done the import of an ICC transform and still need to
|
||||
* export.
|
||||
|
Loading…
Reference in New Issue
Block a user