add im_system_image()
This commit is contained in:
parent
377b76b255
commit
88779a7e3b
@ -11,6 +11,7 @@
|
|||||||
repeating stuff
|
repeating stuff
|
||||||
- im_flood() and friends rewritten, typically 4x faster
|
- im_flood() and friends rewritten, typically 4x faster
|
||||||
- removed --with-cimg option, added --disable-cxx
|
- removed --with-cimg option, added --disable-cxx
|
||||||
|
- added im_system_image() (thanks Roland)
|
||||||
|
|
||||||
26/11/09 started 7.20.3
|
26/11/09 started 7.20.3
|
||||||
- updated en_GB.po translation
|
- updated en_GB.po translation
|
||||||
|
19
TODO
19
TODO
@ -16,25 +16,6 @@
|
|||||||
|
|
||||||
for swapping ... they are asm macros so we should see a speedup
|
for swapping ... they are asm macros so we should see a speedup
|
||||||
|
|
||||||
Something like:
|
|
||||||
|
|
||||||
const char *im_system_image( IMAGE *in, const char *command, char **log );
|
|
||||||
|
|
||||||
Actions:
|
|
||||||
|
|
||||||
- create two empty temporary files
|
|
||||||
- write the image to the first
|
|
||||||
- call system() on the expanded command
|
|
||||||
- capture stdout/stderr into log
|
|
||||||
- delete the temp input file
|
|
||||||
- return the output filename, or NULL if the command failed (log is still
|
|
||||||
returned in this case)
|
|
||||||
|
|
||||||
The caller would open the output file, either with im_open(), or with it's
|
|
||||||
own system (nip2 has it's own open file thing to give progress feedback and
|
|
||||||
use disc for format conversion), and be responsible for deleting the temp
|
|
||||||
output file at some point.
|
|
||||||
|
|
||||||
- can we use conv_sep to speed up the memuse benchmarks?
|
- can we use conv_sep to speed up the memuse benchmarks?
|
||||||
|
|
||||||
- move im_shrink & friends to resample?
|
- move im_shrink & friends to resample?
|
||||||
|
@ -32,6 +32,7 @@ libconversion_la_SOURCES = \
|
|||||||
im_scaleps.c \
|
im_scaleps.c \
|
||||||
im_subsample.c \
|
im_subsample.c \
|
||||||
im_system.c \
|
im_system.c \
|
||||||
|
im_system_image.c \
|
||||||
im_tbjoin.c \
|
im_tbjoin.c \
|
||||||
im_text.c \
|
im_text.c \
|
||||||
im_gaussnoise.c \
|
im_gaussnoise.c \
|
||||||
|
@ -73,7 +73,7 @@ system_vec( im_object *argv )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static im_arg_desc system_arg_types[] = {
|
static im_arg_desc system_args[] = {
|
||||||
IM_INPUT_IMAGE( "im" ),
|
IM_INPUT_IMAGE( "im" ),
|
||||||
IM_INPUT_STRING( "command" ),
|
IM_INPUT_STRING( "command" ),
|
||||||
IM_OUTPUT_STRING( "output" )
|
IM_OUTPUT_STRING( "output" )
|
||||||
@ -84,8 +84,43 @@ static im_function system_desc = {
|
|||||||
"run command on image", /* Description */
|
"run command on image", /* Description */
|
||||||
0, /* Flags */
|
0, /* Flags */
|
||||||
system_vec, /* Dispatch function */
|
system_vec, /* Dispatch function */
|
||||||
IM_NUMBER( system_arg_types ), /* Size of arg list */
|
IM_NUMBER( system_args ), /* Size of arg list */
|
||||||
system_arg_types /* Arg list */
|
system_args /* Arg list */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
system_image_vec( im_object *argv )
|
||||||
|
{
|
||||||
|
IMAGE *in = argv[0];
|
||||||
|
char *in_format = argv[1];
|
||||||
|
char *out_format = argv[2];
|
||||||
|
char *cmd = argv[3];
|
||||||
|
char **log = (char **) &argv[4];
|
||||||
|
char **out_file = (char **) &argv[5];
|
||||||
|
|
||||||
|
*out_file = im_system_image( in, in_format, out_format, cmd, log );
|
||||||
|
if( !*out_file )
|
||||||
|
*out_file = im_strdup( NULL, "" );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static im_arg_desc system_image_args[] = {
|
||||||
|
IM_INPUT_IMAGE( "im" ),
|
||||||
|
IM_INPUT_STRING( "in_format" ),
|
||||||
|
IM_INPUT_STRING( "out_format" ),
|
||||||
|
IM_INPUT_STRING( "command" ),
|
||||||
|
IM_OUTPUT_STRING( "log" ),
|
||||||
|
IM_OUTPUT_STRING( "out_file" )
|
||||||
|
};
|
||||||
|
|
||||||
|
static im_function system_image_desc = {
|
||||||
|
"im_system_image", /* Name */
|
||||||
|
"run command on image, with image output",/* Description */
|
||||||
|
0, /* Flags */
|
||||||
|
system_image_vec, /* Dispatch function */
|
||||||
|
IM_NUMBER( system_image_args ), /* Size of arg list */
|
||||||
|
system_image_args /* Arg list */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1433,6 +1468,7 @@ static im_function *conv_list[] = {
|
|||||||
&scaleps_desc,
|
&scaleps_desc,
|
||||||
&subsample_desc,
|
&subsample_desc,
|
||||||
&system_desc,
|
&system_desc,
|
||||||
|
&system_image_desc,
|
||||||
&tbjoin_desc,
|
&tbjoin_desc,
|
||||||
&text_desc,
|
&text_desc,
|
||||||
&vips2mask_desc,
|
&vips2mask_desc,
|
||||||
|
@ -68,27 +68,6 @@
|
|||||||
#define pclose(f) _pclose(f)
|
#define pclose(f) _pclose(f)
|
||||||
#endif /*OS_WIN32*/
|
#endif /*OS_WIN32*/
|
||||||
|
|
||||||
/* Do popen(), with printf-style args.
|
|
||||||
*/
|
|
||||||
static FILE *
|
|
||||||
popenf( const char *fmt, const char *mode, ... )
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
char buf[IM_MAX_STRSIZE];
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
va_start( args, mode );
|
|
||||||
(void) im_vsnprintf( buf, IM_MAX_STRSIZE, fmt, args );
|
|
||||||
va_end( args );
|
|
||||||
|
|
||||||
if( !(fp = popen( buf, mode )) ) {
|
|
||||||
im_error( "popenf", "%s", strerror( errno ) );
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( fp );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run a command on an IMAGE ... copy to tmp (if necessary), run
|
/* Run a command on an IMAGE ... copy to tmp (if necessary), run
|
||||||
* command on it, unlink (if we copied), return stdout from command.
|
* command on it, unlink (if we copied), return stdout from command.
|
||||||
*/
|
*/
|
||||||
@ -109,12 +88,11 @@ im_system( IMAGE *im, const char *cmd, char **out )
|
|||||||
}
|
}
|
||||||
im_close( disc );
|
im_close( disc );
|
||||||
}
|
}
|
||||||
else if( (fp = popenf( cmd, "r", im->filename )) ) {
|
else if( (fp = im_popenf( cmd, "r", im->filename )) ) {
|
||||||
char line[IM_MAX_STRSIZE];
|
char line[IM_MAX_STRSIZE];
|
||||||
VipsBuf buf;
|
char txt[IM_MAX_STRSIZE];
|
||||||
char str[IM_MAX_STRSIZE];
|
VipsBuf buf = VIPS_BUF_STATIC( txt );
|
||||||
|
|
||||||
vips_buf_init_static( &buf, str, IM_MAX_STRSIZE );
|
|
||||||
while( fgets( line, IM_MAX_STRSIZE, fp ) )
|
while( fgets( line, IM_MAX_STRSIZE, fp ) )
|
||||||
if( !vips_buf_appends( &buf, line ) )
|
if( !vips_buf_appends( &buf, line ) )
|
||||||
break;
|
break;
|
||||||
|
155
libvips/conversion/im_system_image.c
Normal file
155
libvips/conversion/im_system_image.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* im_system_image(): run a command on an image, get an image result
|
||||||
|
*
|
||||||
|
* 8/1/09
|
||||||
|
* - from im_system()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of VIPS.
|
||||||
|
|
||||||
|
VIPS is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif /*HAVE_CONFIG_H*/
|
||||||
|
#include <vips/intl.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif /*HAVE_UNISTD_H*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <vips/vips.h>
|
||||||
|
|
||||||
|
#ifdef WITH_DMALLOC
|
||||||
|
#include <dmalloc.h>
|
||||||
|
#endif /*WITH_DMALLOC*/
|
||||||
|
|
||||||
|
#define IM_MAX_STRSIZE (4096)
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
#define popen(b,m) _popen(b,m)
|
||||||
|
#define pclose(f) _pclose(f)
|
||||||
|
#endif /*OS_WIN32*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
system_image( IMAGE *im,
|
||||||
|
const char *in_name, const char *out_name, const char *cmd_format,
|
||||||
|
char **log )
|
||||||
|
{
|
||||||
|
IMAGE *disc;
|
||||||
|
FILE *fp;
|
||||||
|
char line[IM_MAX_STRSIZE];
|
||||||
|
char txt[IM_MAX_STRSIZE];
|
||||||
|
VipsBuf buf = VIPS_BUF_STATIC( txt );
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if( !(disc = im_open( in_name, "w" )) )
|
||||||
|
return( -1 );
|
||||||
|
if( im_copy( im, disc ) ) {
|
||||||
|
im_close( im );
|
||||||
|
g_unlink( in_name );
|
||||||
|
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
im_close( im );
|
||||||
|
|
||||||
|
if( !(fp = im_popenf( cmd_format, "r", in_name, out_name )) ) {
|
||||||
|
g_unlink( in_name );
|
||||||
|
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( fgets( line, IM_MAX_STRSIZE, fp ) )
|
||||||
|
if( !vips_buf_appends( &buf, line ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
result = pclose( fp );
|
||||||
|
|
||||||
|
g_unlink( in_name );
|
||||||
|
|
||||||
|
if( log )
|
||||||
|
*log = im_strdup( NULL, vips_buf_all( &buf ) );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Run a command on an image, returning a new image.
|
||||||
|
|
||||||
|
"mycommand --dostuff %s -o %s"
|
||||||
|
|
||||||
|
have separate format strings for input and output?
|
||||||
|
|
||||||
|
"%s.jpg"
|
||||||
|
|
||||||
|
Actions:
|
||||||
|
|
||||||
|
- create two empty temporary files
|
||||||
|
- write the image to the first
|
||||||
|
- call system() on the expanded command
|
||||||
|
- capture stdout/stderr into log
|
||||||
|
- delete the temp input file
|
||||||
|
- return the output filename, or NULL if the command failed (log is still
|
||||||
|
set in this case)
|
||||||
|
|
||||||
|
The caller would open the output file, either with im_open(), or with it's
|
||||||
|
own system (nip2 has it's own open file thing to give progress feedback and
|
||||||
|
use disc for format conversion), and be responsible for deleting the temp
|
||||||
|
output file at some point.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
im_system_image( IMAGE *im,
|
||||||
|
const char *in_format, const char *out_format, const char *cmd_format,
|
||||||
|
char **log )
|
||||||
|
{
|
||||||
|
char *in_name;
|
||||||
|
char *out_name;
|
||||||
|
|
||||||
|
if( log )
|
||||||
|
*log = NULL;
|
||||||
|
|
||||||
|
in_name = im__temp_name( in_format );
|
||||||
|
out_name = im__temp_name( in_format );
|
||||||
|
|
||||||
|
if( !in_name ||
|
||||||
|
!out_name ||
|
||||||
|
system_image( im, in_name, out_name, cmd_format, log ) ) {
|
||||||
|
g_free( in_name );
|
||||||
|
g_free( out_name );
|
||||||
|
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
g_free( in_name );
|
||||||
|
|
||||||
|
return( out_name );
|
||||||
|
}
|
@ -111,6 +111,9 @@ int im_subsample( IMAGE *in, IMAGE *out, int x, int y );
|
|||||||
int im_zoom( IMAGE *in, IMAGE *out, int x, int y );
|
int im_zoom( IMAGE *in, IMAGE *out, int x, int y );
|
||||||
|
|
||||||
int im_system( IMAGE *im, const char *cmd, char **out );
|
int im_system( IMAGE *im, const char *cmd, char **out );
|
||||||
|
char *im_system_image( IMAGE *im,
|
||||||
|
const char *in_format, const char *out_format, const char *cmd_format,
|
||||||
|
char **log );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -248,10 +248,13 @@ const char *vips__token_need( const char *buffer, VipsToken need_token,
|
|||||||
|
|
||||||
int im_existsf( const char *name, ... )
|
int im_existsf( const char *name, ... )
|
||||||
__attribute__((format(printf, 1, 2)));
|
__attribute__((format(printf, 1, 2)));
|
||||||
|
FILE *im_popenf( const char *fmt, const char *mode, ... )
|
||||||
|
__attribute__((format(printf, 1, 3)));
|
||||||
int im_ispoweroftwo( int p );
|
int im_ispoweroftwo( int p );
|
||||||
int im_isvips( const char *filename );
|
int im_isvips( const char *filename );
|
||||||
int im_amiMSBfirst( void );
|
int im_amiMSBfirst( void );
|
||||||
|
|
||||||
|
char *im__temp_name( const char *format );
|
||||||
IMAGE *im__open_temp( void );
|
IMAGE *im__open_temp( void );
|
||||||
|
|
||||||
int im_bits_of_fmt( VipsBandFmt fmt );
|
int im_bits_of_fmt( VipsBandFmt fmt );
|
||||||
|
@ -82,6 +82,7 @@ extern "C" {
|
|||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define DEBUG
|
|
||||||
*/
|
*/
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -860,7 +860,7 @@ im__file_read( FILE *fp, const char *name, unsigned int *length_out )
|
|||||||
} while( !feof( fp ) );
|
} while( !feof( fp ) );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "read %d bytes from unseekable stream\n", len );
|
printf( "read %ld bytes from unseekable stream\n", len );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1413,6 +1413,36 @@ im_existsf( const char *name, ... )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
#define popen(b,m) _popen(b,m)
|
||||||
|
#define pclose(f) _pclose(f)
|
||||||
|
#endif /*OS_WIN32*/
|
||||||
|
|
||||||
|
/* Do popen(), with printf-style args.
|
||||||
|
*/
|
||||||
|
FILE *
|
||||||
|
im_popenf( const char *fmt, const char *mode, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char buf[4096];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
va_start( args, mode );
|
||||||
|
(void) im_vsnprintf( buf, 4096, fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "im_popenf: running: %s\n", buf );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( !(fp = popen( buf, mode )) ) {
|
||||||
|
im_error( "popenf", "%s", strerror( errno ) );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( fp );
|
||||||
|
}
|
||||||
|
|
||||||
/* True if an int is a power of two ... 1, 2, 4, 8, 16, 32, etc. Do with just
|
/* True if an int is a power of two ... 1, 2, 4, 8, 16, 32, etc. Do with just
|
||||||
* integer arithmetic for portability. A previous Nicos version using doubles
|
* integer arithmetic for portability. A previous Nicos version using doubles
|
||||||
* and log/log failed on x86 with rounding problems. Return 0 for not
|
* and log/log failed on x86 with rounding problems. Return 0 for not
|
||||||
@ -1478,30 +1508,55 @@ im_amiMSBfirst( void )
|
|||||||
return( 1 );
|
return( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make a temporary file name. The format parameter is something like "%s.jpg"
|
||||||
|
* and will be expanded to something like "/tmp/vips-12-34587.jpg".
|
||||||
|
*
|
||||||
|
* You need to free the result. A real file will also be created, though we
|
||||||
|
* delete it for you.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
im__temp_name( const char *format )
|
||||||
|
{
|
||||||
|
static int serial = 1;
|
||||||
|
|
||||||
|
const char *tmpd;
|
||||||
|
char file[FILENAME_MAX];
|
||||||
|
char file2[FILENAME_MAX];
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if( !(tmpd = g_getenv( "TMPDIR" )) )
|
||||||
|
tmpd = "/tmp";
|
||||||
|
|
||||||
|
im_snprintf( file, FILENAME_MAX, "vips-%d-XXXXXX", serial++ );
|
||||||
|
im_snprintf( file2, FILENAME_MAX, format, file );
|
||||||
|
name = g_build_filename( tmpd, file2, NULL );
|
||||||
|
|
||||||
|
if( (fd = g_mkstemp( name )) == -1 ) {
|
||||||
|
im_error( "tempfile",
|
||||||
|
_( "unable to make temporary file %s" ), name );
|
||||||
|
g_free( name );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
close( fd );
|
||||||
|
g_unlink( name );
|
||||||
|
|
||||||
|
return( name );
|
||||||
|
}
|
||||||
|
|
||||||
/* Make a disc IMAGE which will be automatically unlinked on im_close().
|
/* Make a disc IMAGE which will be automatically unlinked on im_close().
|
||||||
*/
|
*/
|
||||||
IMAGE *
|
IMAGE *
|
||||||
im__open_temp( void )
|
im__open_temp( void )
|
||||||
{
|
{
|
||||||
const char *tmpd;
|
|
||||||
char *name;
|
char *name;
|
||||||
int fd;
|
|
||||||
IMAGE *disc;
|
IMAGE *disc;
|
||||||
|
|
||||||
if( !(tmpd = g_getenv( "TMPDIR" )) )
|
if( !(name = im__temp_name( "%s.v" )) )
|
||||||
tmpd = "/tmp";
|
|
||||||
name = g_build_filename( tmpd, "vips_XXXXXX.v", NULL );
|
|
||||||
|
|
||||||
if( (fd = g_mkstemp( name )) == -1 ) {
|
|
||||||
im_error( "tempfile",
|
|
||||||
_( "unable to make temp file %s" ), name );
|
|
||||||
g_free( name );
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
|
||||||
close( fd );
|
|
||||||
|
|
||||||
if( !(disc = im_open( name, "w" )) ) {
|
if( !(disc = im_open( name, "w" )) ) {
|
||||||
unlink( name );
|
|
||||||
g_free( name );
|
g_free( name );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
@ -1510,7 +1565,7 @@ im__open_temp( void )
|
|||||||
if( im_add_close_callback( disc,
|
if( im_add_close_callback( disc,
|
||||||
(im_callback_fn) unlink, disc->filename, NULL ) ) {
|
(im_callback_fn) unlink, disc->filename, NULL ) ) {
|
||||||
im_close( disc );
|
im_close( disc );
|
||||||
unlink( name );
|
g_unlink( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( disc );
|
return( disc );
|
||||||
|
Loading…
Reference in New Issue
Block a user