added vips_foreign_load_buffer()

This commit is contained in:
John Cupitt 2014-04-22 16:27:43 +01:00
parent aeb3cf3fa3
commit d0f50febbb
16 changed files with 506 additions and 11 deletions

View File

@ -22,7 +22,8 @@
argument order
- support 16-bit palette TIFFs, plus palette TIFFs can have an alpha
- add ".vips" as an alternative suffix for vips files
- add vips_tiffload_buffer()
- added vips_tiffload_buffer()
- added vips_foreign_load_buffer()
6/3/14 started 7.38.6
- grey ramp minimum was wrong

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

@ -505,7 +505,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 +532,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
@ -1473,6 +1513,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

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

@ -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

@ -54,6 +54,7 @@ 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,

View File

@ -1897,15 +1897,27 @@ vips__istifftiled( const char *filename )
return( tiled );
}
gboolean
vips__istiff_buffer( void *buf, size_t len )
{
char *str = (char *) buf;
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 ) )
if( (buf[0] == 'M' && buf[1] == 'M') ||
(buf[0] == 'I' && buf[1] == 'I') )
return( TRUE );
if( vips__get_bytes( filename, buf, 2 ) &&
vips__istiff_buffer( buf, 2 ) )
return( TRUE );
return( FALSE );
}

View File

@ -256,6 +256,7 @@ vips_foreign_load_tiff_buffer_class_init(
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;

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

@ -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

@ -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

@ -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 );
@ -306,6 +314,8 @@ const char *vips_foreign_find_save_options( const char *filename );
*/
int vips_foreign_load( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));