Merge remote-tracking branch 'origin/master' into dzsave-gsf

Conflicts:
	ChangeLog
This commit is contained in:
John Cupitt 2014-04-24 18:35:33 +01:00
commit 6ab49a9af3
27 changed files with 1166 additions and 157 deletions

View File

@ -23,6 +23,10 @@
- support 16-bit palette TIFFs, plus palette TIFFs can have an alpha
- libgsf is now required
- dzsave can directly write a ZIP file
- add ".vips" as an alternative suffix for vips files
- added vips_tiffload_buffer()
- added vips_foreign_load_buffer(), vips_foreign_save_buffer()
- added vips_object_set_from_string()
6/3/14 started 7.38.6
- grey ramp minimum was wrong

26
TODO
View File

@ -1,4 +1,30 @@
- use vips_object_set_from_string() for vips_foreign_load_options() and
friends
- use this for dzsave_buffer
- clean up foreign.c, there seems to be some cruft
- vips_filename_suffix_match() is used by
vips_foreign_load_new_from_foreign_sub(), but it splits on ':' ... argh!
deprecate this thing and stop ':' split
vips_foreign_find_save() should split on [], there's something to find the
start of the rightmost [] pair, use that
see also vips_foreign_find_save_buffer()
- support 1/2/4 bit palette tiff with alpha
- can we use postbuild elsewhere? look at use of "preclose" / "written", etc.

347
compile Executable file
View File

@ -0,0 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -9,7 +9,8 @@ AC_PREREQ(2.62)
# gobject-introspection recommends -Wno-portability
# foreign stops complaints about a missing README (we use README.md instead)
# and missing INSTALL (the standard Gnu INSTALL is not very useful)
AM_INIT_AUTOMAKE([-Wno-portability foreign])
# subdir-objects lets us have dumy.cc in a subdir
AM_INIT_AUTOMAKE([-Wno-portability foreign subdir-objects])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_MACRO_DIR([m4])

View File

@ -73,7 +73,7 @@ vips_gaussblur_build( VipsObject *object )
/* Stop at 20% of max ... bit mean, but means mask radius is roughly
* right.
*/
if( vips_gaussmat( &t[0], gaussblur->radius / 2, 0.2,
if( vips_gaussmat( &t[0], gaussblur->radius / 2.0, 0.2,
"separable", TRUE,
"integer", gaussblur->precision != VIPS_PRECISION_FLOAT,
NULL ) )
@ -162,8 +162,8 @@ vips_gaussblur_init( VipsGaussblur *gaussblur )
* This operator runs vips_gaussmat() and vips_convsep() for you on an image.
*
* @radius is not used directly. Instead the standard deviation of
* vips_gaussmat() is set to @radius / 2 and the minimum amplitude set to 20%.
* This gives a mask radius of approximately @radius pixels.
* vips_gaussmat() is set to @radius / 2.0 and the minimum amplitude set to
* 20%. This gives a mask radius of approximately @radius pixels.
*
* See also: vips_gaussmat(), vips_conv().
*

View File

@ -346,7 +346,7 @@ vips_format_get_flags( VipsFormatClass *format, const char *filename )
/* VIPS format class.
*/
static const char *vips_suffs[] = { ".v", NULL };
static const char *vips_suffs[] = { ".v", ".vips", NULL };
int
im_isvips( const char *filename )

View File

@ -87,10 +87,12 @@
* the file name extension) with JPEG compression.
*
* |[
* vips_foreign_save_options (my_image, "frank.tiff[compression=jpeg]");
* vips_foreign_save_options (my_image, "frank.tiff[compression=jpeg]", NULL);
* ]|
*
* Is the same thing, but with the option in the filename.
* Is the same thing, but with the option in the filename. You can put
* name - value pairs after the filename as well: these will override any
* options set in the filename.
*
* You can also invoke the operations directly, for example:
*
@ -108,9 +110,8 @@
* transparently supported by vips_image_new_from_file() and friends.
*
* VIPS comes with VipsForeign for TIFF, JPEG, PNG, Analyze, PPM, OpenEXR, CSV,
* Matlab, Radiance, RAW, FITS and VIPS. It also
* includes import filters which can
* load with libMagick and with OpenSlide.
* Matlab, Radiance, RAW, FITS, WebP and VIPS. It also includes import filters
* which can load with libMagick and with OpenSlide.
*/
/**
@ -159,7 +160,7 @@
* Add a new loader to VIPS by subclassing #VipsForeignLoad. Subclasses need to
* implement at least @header().
*
* As a complete example, here's the code for the PNG loader, minus the actual
* As a complete example, here's code for a PNG loader, minus the actual
* calls to libpng.
*
* |[
@ -505,7 +506,7 @@ vips_foreign_load_new_from_foreign_sub( VipsForeignLoadClass *load_class,
*
* Searches for an operation you could use to load @filename.
*
* See also: vips_foreign_read().
* See also: vips_foreign_load().
*
* Returns: the name of an operation on success, %NULL on error
*/
@ -532,6 +533,46 @@ vips_foreign_find_load( const char *filename )
return( G_OBJECT_CLASS_NAME( load_class ) );
}
/* Can this VipsForeign open this buffer?
*/
static void *
vips_foreign_find_load_buffer_sub( VipsForeignLoadClass *load_class,
void **buf, size_t *len )
{
if( load_class->is_a_buffer &&
load_class->is_a_buffer( *buf, *len ) )
return( load_class );
return( NULL );
}
/**
* vips_foreign_find_load:
* @filename: file to find a loader for
*
* Searches for an operation you could use to load @filename.
*
* See also: vips_foreign_load_buffer().
*
* Returns: the name of an operation on success, %NULL on error
*/
const char *
vips_foreign_find_load_buffer( void *buf, size_t len )
{
VipsForeignLoadClass *load_class;
if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map(
"VipsForeignLoad",
(VipsSListMap2Fn) vips_foreign_find_load_buffer_sub,
&buf, &len )) ) {
vips_error( "VipsForeignLoad",
"%s", _( "buffer is not in a known format" ) );
return( NULL );
}
return( G_OBJECT_CLASS_NAME( load_class ) );
}
/**
* vips_foreign_find_load_options:
* @filename: file to find a loader for
@ -1022,7 +1063,7 @@ vips_foreign_find_save_sub( VipsForeignSaveClass *save_class,
* @filename may not contain embedded options. See
* vips_foreign_find_save_options() if your filename may have options in.
*
* See also: vips_foreign_write().
* See also: vips_foreign_save().
*
* Returns: the name of an operation on success, %NULL on error
*/
@ -1044,6 +1085,55 @@ vips_foreign_find_save( const char *filename )
return( G_OBJECT_CLASS_NAME( save_class ) );
}
/* Can we write this buffer with this file type?
*/
static void *
vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class,
const char *suffix )
{
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class );
VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class );
if( class->suffs &&
vips_ispostfix( object_class->nickname, "_buffer" ) &&
vips_filename_suffix_match( suffix, class->suffs ) )
return( save_class );
return( NULL );
}
/**
* vips_foreign_find_save_buffer:
* @suffix: name to find a saver for
*
* Searches for an operation you could use to write to a buffer in @suffix
* format.
*
* @filename may not contain embedded options. See
* vips_foreign_find_save_options() if your filename may have options in.
*
* See also: vips_foreign_save_buffer().
*
* Returns: the name of an operation on success, %NULL on error
*/
const char *
vips_foreign_find_save_buffer( const char *suffix )
{
VipsForeignSaveClass *save_class;
if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map(
"VipsForeignSave",
(VipsSListMap2Fn) vips_foreign_find_save_buffer_sub,
(void *) suffix, NULL )) ) {
vips_error( "VipsForeignSave",
_( "\"%s\" is not a known file format" ), suffix );
return( NULL );
}
return( G_OBJECT_CLASS_NAME( save_class ) );
}
/**
* vips_foreign_find_save_options:
* @filename: name to find a saver for
@ -1051,7 +1141,7 @@ vips_foreign_find_save( const char *filename )
* Searches for an operation you could use to write to @filename.
*
* @filename may contain embedded options. See
* vips_foreign_find_save() if your filename does not options in.
* vips_foreign_find_save() if your filename does not have options in.
*
* See also: vips_foreign_write().
*
@ -1473,6 +1563,44 @@ vips_foreign_load( const char *filename, VipsImage **out, ... )
return( result );
}
/**
* vips_foreign_load_buffer:
* @buf: start of memory buffer
* @len: length of memory buffer
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* Loads @buf, @len into @out using the loader recommended by
* vips_foreign_find_load_buffer().
*
* See also: vips_foreign_save(), vips_foreign_load_options().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... )
{
const char *operation;
VipsArea *area;
va_list ap;
int result;
if( !(operation = vips_foreign_find_load_buffer( buf, len )) )
return( -1 );
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( operation, ap, area, out );
va_end( ap );
vips_area_unref( area );
return( result );
}
/**
* vips_foreign_save:
* @in: image to write
@ -1504,6 +1632,99 @@ vips_foreign_save( VipsImage *in, const char *filename, ... )
return( result );
}
/**
* vips_foreign_save_buffer:
* @in: image to write
* @suffix: format to write
* @buf: return buffer start here
* @len: return buffer length here
* @...: %NULL-terminated list of optional named arguments
*
* Saves @in to a memory buffer selected from @suffix. @suffix may also set
* save options, for example it could be ".jpg[Q=80]".
* Save options may also be given
* as a NULL-terminated list of name-value pairs.
*
* See also: vips_foreign_load_buffer().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_save_buffer( VipsImage *in,
const char *suffix, void **buf, size_t *len,
... )
{
char str[VIPS_PATH_MAX];
char *p;
const char *operation_name;
VipsOperation *operation;
VipsArea *area;
va_list ap;
int result;
/* Take any [options] off the suffix.
*/
vips_strncpy( str, suffix, VIPS_PATH_MAX );
if( (p = (char *) vips__find_rightmost_brackets( str )) )
*p = '\0';
if( !(operation_name = vips_foreign_find_save_buffer( str )) )
return( -1 );
if( !(operation = vips_operation_new( operation_name )) )
return( -1 );
g_object_set( operation, "in", in, NULL );
/* Now set any operation args from the options list.
*/
if( (p = (char *) vips__find_rightmost_brackets( suffix )) &&
vips_object_set_from_string( VIPS_OBJECT( operation ), p ) ) {
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
g_object_unref( operation );
return( -1 );
}
/* Set any from varargs.
*/
va_start( ap, len );
result = vips_object_set_valist( VIPS_OBJECT( operation ), ap );
va_end( ap );
if( result ) {
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
g_object_unref( operation );
return( -1 );
}
if( vips_cache_operation_buildp( &operation ) ) {
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
g_object_unref( operation );
return( -1 );
}
g_object_get( operation, "buffer", &area, NULL );
/* Getting @buffer will have upped its count so it'll be safe.
* We can junk all other outputs,
*/
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
g_object_unref( operation );
if( area ) {
if( buf ) {
*buf = area->data;
area->free_fn = NULL;
}
if( len )
*len = area->length;
vips_area_unref( area );
}
return( 0 );
}
/**
* vips_foreign_load_options:
* @filename: file to load
@ -1651,7 +1872,8 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_save_jpeg_file_get_type( void );
extern GType vips_foreign_save_jpeg_buffer_get_type( void );
extern GType vips_foreign_save_jpeg_mime_get_type( void );
extern GType vips_foreign_load_tiff_get_type( void );
extern GType vips_foreign_load_tiff_file_get_type( void );
extern GType vips_foreign_load_tiff_buffer_get_type( void );
extern GType vips_foreign_save_tiff_get_type( void );
extern GType vips_foreign_load_vips_get_type( void );
extern GType vips_foreign_save_vips_get_type( void );
@ -1709,7 +1931,8 @@ vips_foreign_operation_init( void )
#endif /*HAVE_LIBWEBP*/
#ifdef HAVE_TIFF
vips_foreign_load_tiff_get_type();
vips_foreign_load_tiff_file_get_type();
vips_foreign_load_tiff_buffer_get_type();
vips_foreign_save_tiff_get_type();
#endif /*HAVE_TIFF*/
@ -1807,6 +2030,44 @@ vips_tiffload( const char *filename, VipsImage **out, ... )
return( result );
}
/**
* vips_tiffload_buffer:
* @buf: memory area to load
* @len: size of memory area
* @out: image to write
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* @page: load this page
*
* Read a TIFF-formatted memory block into a VIPS image. Exactly as
* vips_tiffload(), but read from a memory source.
*
* See also: vips_tiffload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
{
va_list ap;
VipsArea *area;
int result;
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( "tiffload_buffer", ap, area, out );
va_end( ap );
vips_area_unref( area );
return( result );
}
/**
* vips_tiffsave:
* @in: image to save
@ -1899,46 +2160,6 @@ vips_tiffsave( VipsImage *in, const char *filename, ... )
return( result );
}
/**
* vips_jpegload_buffer:
* @buf: memory area to load
* @len: size of memory area
* @out: image to write
* @...: %NULL-terminated list of optional named arguments
*
* Read a JPEG-formatted memory block into a VIPS image. It can read most
* 8-bit JPEG images, including CMYK and YCbCr.
*
* This function is handy for processing JPEG image thumbnails.
*
* Caution: on return only the header will have been read, the pixel data is
* not decompressed until the first pixel is read. Therefore you must not free
* @buf until you have read pixel data from @out.
*
* See also: vips_jpegload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... )
{
va_list ap;
VipsArea *area;
int result;
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( "jpegload_buffer", ap, area, out );
va_end( ap );
vips_area_unref( area );
return( result );
}
/**
* vips_jpegload:
* @filename: file to load
@ -2008,6 +2229,45 @@ vips_jpegload( const char *filename, VipsImage **out, ... )
return( result );
}
/**
* vips_jpegload_buffer:
* @buf: memory area to load
* @len: size of memory area
* @out: image to write
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* @shrink: shrink by this much on load
* @fail: fail on warnings
*
* Read a JPEG-formatted memory block into a VIPS image. Exactly as
* vips_jpegload(), but read from a memory buffer.
*
* See also: vips_jpegload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... )
{
va_list ap;
VipsArea *area;
int result;
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( "jpegload_buffer", ap, area, out );
va_end( ap );
vips_area_unref( area );
return( result );
}
/**
* vips_jpegsave:
* @in: image to save
@ -2121,7 +2381,7 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
*buf = area->data;
area->free_fn = NULL;
}
if( buf )
if( len )
*len = area->length;
vips_area_unref( area );
@ -2282,7 +2542,7 @@ vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
*buf = area->data;
area->free_fn = NULL;
}
if( buf )
if( len )
*len = area->length;
vips_area_unref( area );
@ -2611,7 +2871,7 @@ vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
*buf = area->data;
area->free_fn = NULL;
}
if( buf )
if( len )
*len = area->length;
vips_area_unref( area );

View File

@ -1247,14 +1247,27 @@ vips__jpeg_read_buffer( void *buf, size_t len, VipsImage *out,
return( result );
}
int
vips__isjpeg_buffer( void *buf, size_t len )
{
guchar *str = (guchar *) buf;
if( len >= 2 &&
str[0] == 0xff &&
str[1] == 0xd8 )
return( 1 );
return( 0 );
}
int
vips__isjpeg( const char *filename )
{
unsigned char buf[2];
if( vips__get_bytes( filename, buf, 2 ) )
if( (int) buf[0] == 0xff && (int) buf[1] == 0xd8 )
return( 1 );
if( vips__get_bytes( filename, buf, 2 ) &&
vips__isjpeg_buffer( buf, 2 ) )
return( 1 );
return( 0 );
}

View File

@ -287,6 +287,12 @@ vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load )
return( 0 );
}
static gboolean
vips_foreign_load_jpeg_buffer_is_a( void *buf, size_t len )
{
return( vips__isjpeg_buffer( buf, len ) );
}
static void
vips_foreign_load_jpeg_buffer_class_init(
VipsForeignLoadJpegBufferClass *class )
@ -301,6 +307,7 @@ vips_foreign_load_jpeg_buffer_class_init(
object_class->nickname = "jpegload_buffer";
object_class->description = _( "load jpeg from buffer" );
load_class->is_a_buffer = vips_foreign_load_jpeg_buffer_is_a;
load_class->header = vips_foreign_load_jpeg_buffer_header;
load_class->load = vips_foreign_load_jpeg_buffer_load;

View File

@ -112,6 +112,7 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
gobject_class->set_property = vips_object_set_property;
@ -120,6 +121,8 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
object_class->nickname = "jpegsave_base";
object_class->description = _( "save jpeg" );
foreign_class->suffs = vips__jpeg_suffs;
save_class->saveable = VIPS_SAVEABLE_RGB_CMYK;
save_class->format_table = bandfmt_jpeg;
@ -204,7 +207,6 @@ vips_foreign_save_jpeg_file_class_init( VipsForeignSaveJpegFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -213,8 +215,6 @@ vips_foreign_save_jpeg_file_class_init( VipsForeignSaveJpegFileClass *class )
object_class->description = _( "save image to jpeg file" );
object_class->build = vips_foreign_save_jpeg_file_build;
foreign_class->suffs = vips__jpeg_suffs;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to save to" ),

View File

@ -198,6 +198,7 @@ vips_foreign_load_png_buffer_class_init( VipsForeignLoadPngBufferClass *class )
object_class->nickname = "pngload_buffer";
object_class->description = _( "load png from buffer" );
load_class->is_a_buffer = vips__png_ispng_buffer;
load_class->header = vips_foreign_load_png_buffer_header;
load_class->load = vips_foreign_load_png_buffer_load;

View File

@ -50,12 +50,18 @@ int vips__tiff_write( VipsImage *in, const char *filename,
gboolean bigtiff,
gboolean rgbjpeg );
int vips__tiff_read( const char *filename, VipsImage *out, int page,
gboolean readbehind );
int vips__tiff_read_header( const char *filename, VipsImage *out, int page );
int vips__tiff_read( const char *filename, VipsImage *out,
int page, gboolean readbehind );
gboolean vips__istifftiled( const char *filename );
gboolean vips__istiff_buffer( void *buf, size_t len );
gboolean vips__istiff( const char *filename );
int vips__tiff_read_header_buffer( void *buf, size_t len, VipsImage *out,
int page );
int vips__tiff_read_buffer( void *buf, size_t len, VipsImage *out,
int page, gboolean readbehind );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -144,6 +144,8 @@
* 11/4/14
* - support 16 bits per sample palette images
* - palette images can have an alpha
* 22/4/14
* - add read from buffer
*/
/*
@ -208,6 +210,8 @@ typedef struct _ReadTiff {
/* Parameters.
*/
char *filename;
void *buf;
size_t len;
VipsImage *out;
int page;
gboolean readbehind;
@ -225,6 +229,10 @@ typedef struct _ReadTiff {
*/
gboolean memcpy;
/* The current 'file pointer' for memory buffers.
*/
size_t pos;
/* Geometry.
*/
uint32 twidth, theight; /* Tile size */
@ -1635,15 +1643,16 @@ readtiff_destroy( VipsObject *object, ReadTiff *rtiff )
}
static ReadTiff *
readtiff_new( const char *filename, VipsImage *out, int page,
gboolean readbehind )
readtiff_new( VipsImage *out, int page, gboolean readbehind )
{
ReadTiff *rtiff;
if( !(rtiff = VIPS_NEW( out, ReadTiff )) )
return( NULL );
rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename );
rtiff->filename = NULL;
rtiff->buf = NULL;
rtiff->len = 0;
rtiff->out = out;
rtiff->page = page;
rtiff->readbehind = readbehind;
@ -1651,6 +1660,7 @@ readtiff_new( const char *filename, VipsImage *out, int page,
rtiff->sfn = NULL;
rtiff->client = NULL;
rtiff->memcpy = FALSE;
rtiff->pos = 0;
rtiff->twidth = 0;
rtiff->theight = 0;
rtiff->separate = FALSE;
@ -1669,33 +1679,138 @@ readtiff_new( const char *filename, VipsImage *out, int page,
return( rtiff );
}
/* Pull out the nth directory from a TIFF file.
*/
static TIFF *
get_directory( const char *filename, int page )
static ReadTiff *
readtiff_new_filename( const char *filename, VipsImage *out, int page,
gboolean readbehind )
{
TIFF *tif;
ReadTiff *rtiff;
int i;
if( !(rtiff = readtiff_new( out, page, readbehind )) )
return( NULL );
rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename );
/* No mmap --- no performance advantage with libtiff, and it burns up
* our VM if the tiff file is large.
*/
if( !(tif = TIFFOpen( filename, "rm" )) ) {
vips_error( "tiff2vips",
_( "unable to open \"%s\" for input" ),
if( !(rtiff->tiff = TIFFOpen( filename, "rm" )) ) {
vips_error( "tiff2vips", _( "unable to open \"%s\" for input" ),
filename );
return( NULL );
}
for( i = 0; i < page; i++ )
if( !TIFFReadDirectory( tif ) ) {
/* Run out of directories.
*/
TIFFClose( tif );
if( !TIFFReadDirectory( rtiff->tiff ) ) {
vips_error( "tiff2vips",
_( "TIFF does not contain page %d" ),
rtiff->page );
return( NULL );
}
return( tif );
return( rtiff );
}
static tsize_t
my_tiff_read( thandle_t st, tdata_t buffer, tsize_t size )
{
ReadTiff *rtiff = (ReadTiff *) st;
size_t available = rtiff->len - rtiff->pos;
size_t copy = VIPS_MIN( size, available );
memcpy( buffer, rtiff->buf + rtiff->pos, copy );
rtiff->pos += copy;
return( copy );
}
static tsize_t
my_tiff_write( thandle_t st, tdata_t buffer, tsize_t size )
{
g_assert( 0 );
return( 0 );
}
static int
my_tiff_close( thandle_t st )
{
return 0;
}
static toff_t
my_tiff_seek( thandle_t st, toff_t pos, int whence )
{
ReadTiff *rtiff = (ReadTiff *) st;
if( whence == SEEK_SET )
rtiff->pos = pos;
else if( whence == SEEK_CUR )
rtiff->pos += pos;
else if( whence == SEEK_END )
rtiff->pos = rtiff->len + pos;
else
g_assert( 0 );
return( rtiff->pos );
}
static toff_t
my_tiff_size( thandle_t st )
{
ReadTiff *rtiff = (ReadTiff *) st;
return( rtiff->len );
}
static int
my_tiff_map( thandle_t st, tdata_t *start, toff_t *len )
{
g_assert( 0 );
return 0;
}
static void
my_tiff_unmap( thandle_t st, tdata_t start, toff_t len )
{
g_assert( 0 );
return;
}
static ReadTiff *
readtiff_new_buffer( void *buf, size_t len, VipsImage *out, int page,
gboolean readbehind )
{
ReadTiff *rtiff;
int i;
if( !(rtiff = readtiff_new( out, page, readbehind )) )
return( NULL );
rtiff->buf = buf;
rtiff->len = len;
if( !(rtiff->tiff = TIFFClientOpen( "memory buffer", "rm",
(thandle_t) rtiff,
my_tiff_read, my_tiff_write, my_tiff_seek, my_tiff_close,
my_tiff_size, my_tiff_map, my_tiff_unmap )) ) {
vips_error( "tiff2vips", "%s",
_( "unable to open memory buffer for input" ) );
return( NULL );
}
for( i = 0; i < page; i++ )
if( !TIFFReadDirectory( rtiff->tiff ) ) {
vips_error( "tiff2vips",
_( "TIFF does not contain page %d" ),
rtiff->page );
return( NULL );
}
return( rtiff );
}
/*
@ -1732,15 +1847,10 @@ vips__tiff_read( const char *filename, VipsImage *out, int page,
vips__tiff_init();
if( !(rtiff = readtiff_new( filename, out, page, readbehind )) )
if( !(rtiff = readtiff_new_filename( filename,
out, page, readbehind )) )
return( -1 );
if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) {
vips_error( "tiff2vips", _( "TIFF file does not "
"contain page %d" ), rtiff->page );
return( -1 );
}
if( TIFFIsTiled( rtiff->tiff ) ) {
if( read_tilewise( rtiff, out ) )
return( -1 );
@ -1760,16 +1870,9 @@ vips__tiff_read_header( const char *filename, VipsImage *out, int page )
vips__tiff_init();
if( !(rtiff = readtiff_new( filename, out, page, FALSE )) )
if( !(rtiff = readtiff_new_filename( filename, out, page, FALSE )) )
return( -1 );
if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) {
vips_error( "tiff2vips",
_( "TIFF file does not contain page %d" ),
rtiff->page );
return( -1 );
}
if( parse_header( rtiff, out ) )
return( -1 );
@ -1795,16 +1898,72 @@ vips__istifftiled( const char *filename )
}
gboolean
vips__istiff( const char *filename )
vips__istiff_buffer( void *buf, size_t len )
{
unsigned char buf[2];
char *str = (char *) buf;
if( vips__get_bytes( filename, buf, 2 ) )
if( (buf[0] == 'M' && buf[1] == 'M') ||
(buf[0] == 'I' && buf[1] == 'I') )
return( TRUE );
if( len >= 2 &&
((str[0] == 'M' && str[1] == 'M') ||
(str[0] == 'I' && str[1] == 'I')) )
return( TRUE );
return( FALSE );
}
gboolean
vips__istiff( const char *filename )
{
unsigned char buf[2];
if( vips__get_bytes( filename, buf, 2 ) &&
vips__istiff_buffer( buf, 2 ) )
return( TRUE );
return( FALSE );
}
int
vips__tiff_read_header_buffer( void *buf, size_t len, VipsImage *out, int page )
{
ReadTiff *rtiff;
vips__tiff_init();
if( !(rtiff = readtiff_new_buffer( buf, len, out, page, FALSE )) )
return( -1 );
if( parse_header( rtiff, out ) )
return( -1 );
return( 0 );
}
int
vips__tiff_read_buffer( void *buf, size_t len, VipsImage *out,
int page, gboolean readbehind )
{
ReadTiff *rtiff;
#ifdef DEBUG
printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() );
printf( "tiff2vips: libtiff starting for %s\n", filename );
#endif /*DEBUG*/
vips__tiff_init();
if( !(rtiff = readtiff_new_buffer( buf, len, out, page, readbehind )) )
return( -1 );
if( TIFFIsTiled( rtiff->tiff ) ) {
if( read_tilewise( rtiff, out ) )
return( -1 );
}
else {
if( read_stripwise( rtiff, out ) )
return( -1 );
}
return( 0 );
}
#endif /*HAVE_TIFF*/

View File

@ -55,10 +55,6 @@
typedef struct _VipsForeignLoadTiff {
VipsForeignLoad parent_object;
/* Filename for load.
*/
char *filename;
/* Load this page.
*/
int page;
@ -67,11 +63,58 @@ typedef struct _VipsForeignLoadTiff {
typedef VipsForeignLoadClass VipsForeignLoadTiffClass;
G_DEFINE_TYPE( VipsForeignLoadTiff, vips_foreign_load_tiff,
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadTiff, vips_foreign_load_tiff,
VIPS_TYPE_FOREIGN_LOAD );
static void
vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
/* Other libraries may be using libtiff, we want to capture tiff
* warning and error as soon as we can.
*
* This class init will be triggered during startup.
*/
vips__tiff_init();
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "tiffload_base";
object_class->description = _( "load tiff" );
VIPS_ARG_INT( class, "page", 10,
_( "Page" ),
_( "Load this page from the image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiff, page ),
0, 100000, 0 );
}
static void
vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff )
{
tiff->page = 0;
}
typedef struct _VipsForeignLoadTiffFile {
VipsForeignLoadTiff parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadTiffFile;
typedef VipsForeignLoadTiffClass VipsForeignLoadTiffFileClass;
G_DEFINE_TYPE( VipsForeignLoadTiffFile, vips_foreign_load_tiff_file,
vips_foreign_load_tiff_get_type() );
static VipsForeignFlags
vips_foreign_load_tiff_get_flags_filename( const char *filename )
vips_foreign_load_tiff_file_get_flags_filename( const char *filename )
{
VipsForeignFlags flags;
@ -85,30 +128,33 @@ vips_foreign_load_tiff_get_flags_filename( const char *filename )
}
static VipsForeignFlags
vips_foreign_load_tiff_get_flags( VipsForeignLoad *load )
vips_foreign_load_tiff_file_get_flags( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
return( vips_foreign_load_tiff_get_flags_filename( tiff->filename ) );
return( vips_foreign_load_tiff_file_get_flags_filename(
file->filename ) );
}
static int
vips_foreign_load_tiff_header( VipsForeignLoad *load )
vips_foreign_load_tiff_file_header( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
if( vips__tiff_read_header( tiff->filename, load->out, tiff->page ) )
if( vips__tiff_read_header( file->filename, load->out, tiff->page ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_tiff_load( VipsForeignLoad *load )
vips_foreign_load_tiff_file_load( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
if( vips__tiff_read( tiff->filename, load->real, tiff->page,
if( vips__tiff_read( file->filename, load->real, tiff->page,
load->access == VIPS_ACCESS_SEQUENTIAL ) )
return( -1 );
@ -118,20 +164,13 @@ vips_foreign_load_tiff_load( VipsForeignLoad *load )
const char *vips__foreign_tiff_suffs[] = { ".tif", ".tiff", NULL };
static void
vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class )
vips_foreign_load_tiff_file_class_init( VipsForeignLoadTiffFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
/* Other libraries may be using libtiff, we want to capture tiff
* warning and error as soon as we can.
*
* This class init will be triggered during startup.
*/
vips__tiff_init();
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -142,28 +181,95 @@ vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class )
load_class->is_a = vips__istiff;
load_class->get_flags_filename =
vips_foreign_load_tiff_get_flags_filename;
load_class->get_flags = vips_foreign_load_tiff_get_flags;
load_class->header = vips_foreign_load_tiff_header;
load_class->load = vips_foreign_load_tiff_load;
vips_foreign_load_tiff_file_get_flags_filename;
load_class->get_flags = vips_foreign_load_tiff_file_get_flags;
load_class->header = vips_foreign_load_tiff_file_header;
load_class->load = vips_foreign_load_tiff_file_load;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiff, filename ),
G_STRUCT_OFFSET( VipsForeignLoadTiffFile, filename ),
NULL );
VIPS_ARG_INT( class, "page", 10,
_( "Page" ),
_( "Load this page from the file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiff, page ),
0, 100000, 0 );
}
static void
vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff )
vips_foreign_load_tiff_file_init( VipsForeignLoadTiffFile *file )
{
}
typedef struct _VipsForeignLoadTiffBuffer {
VipsForeignLoadTiff parent_object;
/* Load from a buffer.
*/
VipsArea *buf;
} VipsForeignLoadTiffBuffer;
typedef VipsForeignLoadTiffClass VipsForeignLoadTiffBufferClass;
G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer,
vips_foreign_load_tiff_get_type() );
static int
vips_foreign_load_tiff_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load;
if( vips__tiff_read_header_buffer(
buffer->buf->data, buffer->buf->length, load->out,
tiff->page ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load;
if( vips__tiff_read_buffer(
buffer->buf->data, buffer->buf->length, load->real,
tiff->page,
load->access == VIPS_ACCESS_SEQUENTIAL ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_tiff_buffer_class_init(
VipsForeignLoadTiffBufferClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "tiffload_buffer";
object_class->description = _( "load tiff from buffer" );
load_class->is_a_buffer = vips__istiff_buffer;
load_class->header = vips_foreign_load_tiff_buffer_header;
load_class->load = vips_foreign_load_tiff_buffer_load;
VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ),
_( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiffBuffer, buf ),
VIPS_TYPE_BLOB );
}
static void
vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer )
{
}

View File

@ -46,6 +46,7 @@ int vips__jpeg_write_buffer( VipsImage *in,
gboolean optimize_coding, gboolean progressive, gboolean strip,
gboolean no_subsample );
int vips__isjpeg_buffer( void *buf, size_t len );
int vips__isjpeg( const char *filename );
int vips__jpeg_read_file( const char *name, VipsImage *out,
gboolean header_only, int shrink, gboolean fail, gboolean readbehind );

View File

@ -105,7 +105,7 @@ vips_foreign_load_vips_header( VipsForeignLoad *load )
return( 0 );
}
static const char *vips_suffs[] = { ".v", NULL };
const char *vips__suffs[] = { ".v", ".vips", NULL };
static void
vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class )
@ -121,7 +121,7 @@ vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class )
object_class->nickname = "vipsload";
object_class->description = _( "load vips from file" );
foreign_class->suffs = vips_suffs;
foreign_class->suffs = vips__suffs;
load_class->is_a = vips_foreign_load_vips_is_a;
load_class->get_flags = vips_foreign_load_vips_get_flags;

View File

@ -561,13 +561,23 @@ vips__png_read( const char *filename, VipsImage *out, gboolean readbehind )
return( 0 );
}
int
vips__png_ispng_buffer( void *buf, size_t len )
{
if( len >= 8 &&
!png_sig_cmp( buf, 0, 8 ) )
return( TRUE );
return( FALSE );
}
int
vips__png_ispng( const char *filename )
{
unsigned char buf[8];
return( vips__get_bytes( filename, buf, 8 ) &&
!png_sig_cmp( buf, 0, 8 ) );
vips__png_ispng_buffer( buf, 8 ) );
}
static void

View File

@ -37,6 +37,7 @@ extern "C" {
int vips__png_header( const char *name, VipsImage *out );
int vips__png_read( const char *name, VipsImage *out, gboolean readbehind );
int vips__png_ispng_buffer( void *buf, size_t len );
int vips__png_ispng( const char *filename );
gboolean vips__png_isinterlaced( const char *filename );
extern const char *vips__png_suffs[];

View File

@ -75,7 +75,9 @@ vips_foreign_save_vips_build( VipsObject *object )
return( 0 );
}
static const char *vips_suffs[] = { ".v", NULL };
/* From vipsload.c.
*/
extern const char *vips__suffs[];
static void
vips_foreign_save_vips_class_init( VipsForeignSaveVipsClass *class )
@ -94,7 +96,7 @@ vips_foreign_save_vips_class_init( VipsForeignSaveVipsClass *class )
object_class->description = _( "save image to vips file" );
object_class->build = vips_foreign_save_vips_build;
foreign_class->suffs = vips_suffs;
foreign_class->suffs = vips__suffs;
save_class->saveable = VIPS_SAVEABLE_ANY;
for( i = 0; i < VIPS_CODING_LAST; i++ )

View File

@ -37,6 +37,7 @@ extern "C" {
extern const char *vips__webp_suffs[];
int vips__iswebp_buffer( void *buf, size_t len );
int vips__iswebp( const char *filename );
int vips__webp_read_file_header( const char *name, VipsImage *out );

View File

@ -87,13 +87,23 @@ typedef struct {
WebPIDecoder *idec;
} Read;
int
vips__iswebp_buffer( void *buf, size_t len )
{
if( len >= MINIMAL_HEADER &&
WebPGetInfo( buf, MINIMAL_HEADER, NULL, NULL ) )
return( 1 );
return( 0 );
}
int
vips__iswebp( const char *filename )
{
unsigned char header[MINIMAL_HEADER];
if( vips__get_bytes( filename, header, MINIMAL_HEADER ) &&
WebPGetInfo( header, MINIMAL_HEADER, NULL, NULL ) )
vips__iswebp_buffer( header, MINIMAL_HEADER ) )
return( 1 );
return( 0 );

View File

@ -233,6 +233,7 @@ vips_foreign_load_webp_buffer_class_init(
object_class->nickname = "webpload_buffer";
object_class->description = _( "load webp from buffer" );
load_class->is_a_buffer = vips__iswebp_buffer;
load_class->header = vips_foreign_load_webp_buffer_header;
load_class->load = vips_foreign_load_webp_buffer_load;

View File

@ -81,6 +81,7 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
gobject_class->set_property = vips_object_set_property;
@ -89,6 +90,8 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class )
object_class->nickname = "webpsave_base";
object_class->description = _( "save webp" );
foreign_class->suffs = vips__webp_suffs;
save_class->saveable = VIPS_SAVEABLE_RGBA;
save_class->format_table = bandfmt_webp;
@ -151,7 +154,6 @@ vips_foreign_save_webp_file_class_init( VipsForeignSaveWebpFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -160,8 +162,6 @@ vips_foreign_save_webp_file_class_init( VipsForeignSaveWebpFileClass *class )
object_class->description = _( "save image to webp file" );
object_class->build = vips_foreign_save_webp_file_build;
foreign_class->suffs = vips__webp_suffs;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to save to" ),

View File

@ -161,6 +161,13 @@ typedef struct _VipsForeignLoadClass {
*/
gboolean (*is_a)( const char * );
/* Is a buffer in this format.
*
* This function should return %TRUE if the buffer contains an image of
* this type.
*/
gboolean (*is_a_buffer)( void *, size_t );
/* Get the flags from a filename.
*
* This function should examine the file and return a set
@ -207,6 +214,7 @@ typedef struct _VipsForeignLoadClass {
GType vips_foreign_load_get_type( void );
const char *vips_foreign_find_load( const char *filename );
const char *vips_foreign_find_load_buffer( void *buf, size_t len );
const char *vips_foreign_find_load_options( const char *filename );
VipsForeignFlags vips_foreign_flags( const char *loader, const char *filename );
@ -300,6 +308,7 @@ typedef struct _VipsForeignSaveClass {
GType vips_foreign_save_get_type( void );
const char *vips_foreign_find_save( const char *filename );
const char * vips_foreign_find_save_buffer( const char *suffix );
const char *vips_foreign_find_save_options( const char *filename );
/* Read/write an image convenience functions.
@ -314,6 +323,12 @@ int vips_foreign_load_options( const char *filename, VipsImage **out, ... )
int vips_foreign_save_options( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save_buffer( VipsImage *in,
const char *suffix, void **buf, size_t *len, ... )
__attribute__((sentinel));
int vips_openslideload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
@ -397,6 +412,8 @@ typedef enum {
int vips_tiffload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
__attribute__((sentinel));
int vips_tiffsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));

View File

@ -587,6 +587,7 @@ VipsObject *vips_object_new( GType type,
int vips_object_set_valist( VipsObject *object, va_list ap );
int vips_object_set( VipsObject *object, ... )
__attribute__((sentinel));
int vips_object_set_from_string( VipsObject *object, const char *string );
VipsObject *vips_object_new_from_string( VipsObjectClass *object_class,
const char *p );

View File

@ -2054,7 +2054,7 @@ vips_object_set_valist( VipsObject *object, va_list ap )
* Input arguments are given in-line, output arguments are given as pointers
* to where the output value should be written.
*
* See also: vips_object_set_valist().
* See also: vips_object_set_valist(), vips_object_set_from_string().
*
* Returns: 0 on success, -1 on error
*/
@ -2072,7 +2072,7 @@ vips_object_set( VipsObject *object, ... )
}
/* Set object args from a string. @p should be the initial left bracket and
* there should be no tokens after the matching right bracket.
* there should be no tokens after the matching right bracket. @p is modified.
*/
static int
vips_object_set_args( VipsObject *object, const char *p )
@ -2154,6 +2154,44 @@ vips_object_set_args( VipsObject *object, const char *p )
return( 0 );
}
/**
* vips_object_set_from_string:
* @object: object to set arguments on
* @string: arguments as a string
*
* Set object arguments from a string. The string can be something like
* "a=12", or "a = 12, b = 13", or "fred". The string can optionally be
* enclosed in brackets.
*
* You'd typically use this between creating the object and building it.
*
* See also: vips_object_set(), vips_object_build(),
* vips_cache_operation_buildp().
*
* Returns: 0 on success, -1 on error
*/
int
vips_object_set_from_string( VipsObject *object, const char *string )
{
const char *q;
VipsToken token;
char buffer[VIPS_PATH_MAX];
char str[VIPS_PATH_MAX];
vips_strncpy( buffer, string, VIPS_PATH_MAX );
/* Does string start with a bracket? If it doesn't, enclose the whole
* thing in [].
*/
if( !(q = vips__token_get( buffer, &token, str, VIPS_PATH_MAX )) ||
token != VIPS_TOKEN_LEFT )
vips_snprintf( buffer, VIPS_PATH_MAX, "[%s]", string );
else
vips_strncpy( buffer, string, VIPS_PATH_MAX );
return( vips_object_set_args( object, buffer ) );
}
VipsObject *
vips_object_new_from_string( VipsObjectClass *object_class, const char *p )
{
@ -2177,7 +2215,7 @@ vips_object_new_from_string( VipsObjectClass *object_class, const char *p )
/* More tokens there? Set any other args.
*/
if( q &&
vips_object_set_args( object, q ) ) {
vips_object_set_from_string( object, q ) ) {
g_object_unref( object );
return( NULL );
}

View File

@ -765,16 +765,13 @@ vips__file_open_write( const char *filename, gboolean text_mode )
char *
vips__file_read( FILE *fp, const char *filename, unsigned int *length_out )
{
long len;
gint64 len;
size_t read;
char *str;
/* Find length.
*/
fseek( fp, 0L, 2 );
len = ftell( fp );
if( len > 20 * 1024 * 1024 ) {
/* Seems crazy!
len = vips_file_length( fileno( fp ) );
if( len > 1024 * 1024 * 1024 ) {
/* Over a gb? Seems crazy!
*/
vips_error( "vips__file_read",
_( "\"%s\" too long" ), filename );