add im_system_image()
This commit is contained in:
parent
377b76b255
commit
88779a7e3b
@ -11,6 +11,7 @@
|
||||
repeating stuff
|
||||
- im_flood() and friends rewritten, typically 4x faster
|
||||
- removed --with-cimg option, added --disable-cxx
|
||||
- added im_system_image() (thanks Roland)
|
||||
|
||||
26/11/09 started 7.20.3
|
||||
- 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
|
||||
|
||||
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?
|
||||
|
||||
- move im_shrink & friends to resample?
|
||||
|
@ -32,6 +32,7 @@ libconversion_la_SOURCES = \
|
||||
im_scaleps.c \
|
||||
im_subsample.c \
|
||||
im_system.c \
|
||||
im_system_image.c \
|
||||
im_tbjoin.c \
|
||||
im_text.c \
|
||||
im_gaussnoise.c \
|
||||
|
@ -73,7 +73,7 @@ system_vec( im_object *argv )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static im_arg_desc system_arg_types[] = {
|
||||
static im_arg_desc system_args[] = {
|
||||
IM_INPUT_IMAGE( "im" ),
|
||||
IM_INPUT_STRING( "command" ),
|
||||
IM_OUTPUT_STRING( "output" )
|
||||
@ -84,8 +84,43 @@ static im_function system_desc = {
|
||||
"run command on image", /* Description */
|
||||
0, /* Flags */
|
||||
system_vec, /* Dispatch function */
|
||||
IM_NUMBER( system_arg_types ), /* Size of arg list */
|
||||
system_arg_types /* Arg list */
|
||||
IM_NUMBER( system_args ), /* Size of 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
|
||||
@ -1433,6 +1468,7 @@ static im_function *conv_list[] = {
|
||||
&scaleps_desc,
|
||||
&subsample_desc,
|
||||
&system_desc,
|
||||
&system_image_desc,
|
||||
&tbjoin_desc,
|
||||
&text_desc,
|
||||
&vips2mask_desc,
|
||||
|
@ -68,27 +68,6 @@
|
||||
#define pclose(f) _pclose(f)
|
||||
#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
|
||||
* 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 );
|
||||
}
|
||||
else if( (fp = popenf( cmd, "r", im->filename )) ) {
|
||||
else if( (fp = im_popenf( cmd, "r", im->filename )) ) {
|
||||
char line[IM_MAX_STRSIZE];
|
||||
VipsBuf buf;
|
||||
char str[IM_MAX_STRSIZE];
|
||||
char txt[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 ) )
|
||||
if( !vips_buf_appends( &buf, line ) )
|
||||
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_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
|
||||
}
|
||||
|
@ -248,10 +248,13 @@ const char *vips__token_need( const char *buffer, VipsToken need_token,
|
||||
|
||||
int im_existsf( const char *name, ... )
|
||||
__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_isvips( const char *filename );
|
||||
int im_amiMSBfirst( void );
|
||||
|
||||
char *im__temp_name( const char *format );
|
||||
IMAGE *im__open_temp( void );
|
||||
|
||||
int im_bits_of_fmt( VipsBandFmt fmt );
|
||||
|
@ -82,6 +82,7 @@ extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gmodule.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#define DEBUG
|
||||
*/
|
||||
#define DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -860,7 +860,7 @@ im__file_read( FILE *fp, const char *name, unsigned int *length_out )
|
||||
} while( !feof( fp ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "read %d bytes from unseekable stream\n", len );
|
||||
printf( "read %ld bytes from unseekable stream\n", len );
|
||||
#endif /*DEBUG*/
|
||||
}
|
||||
else {
|
||||
@ -1413,6 +1413,36 @@ im_existsf( const char *name, ... )
|
||||
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
|
||||
* integer arithmetic for portability. A previous Nicos version using doubles
|
||||
* and log/log failed on x86 with rounding problems. Return 0 for not
|
||||
@ -1478,30 +1508,55 @@ im_amiMSBfirst( void )
|
||||
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().
|
||||
*/
|
||||
IMAGE *
|
||||
im__open_temp( void )
|
||||
{
|
||||
const char *tmpd;
|
||||
char *name;
|
||||
int fd;
|
||||
IMAGE *disc;
|
||||
|
||||
if( !(tmpd = g_getenv( "TMPDIR" )) )
|
||||
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 );
|
||||
if( !(name = im__temp_name( "%s.v" )) )
|
||||
return( NULL );
|
||||
}
|
||||
close( fd );
|
||||
|
||||
if( !(disc = im_open( name, "w" )) ) {
|
||||
unlink( name );
|
||||
g_free( name );
|
||||
return( NULL );
|
||||
}
|
||||
@ -1510,7 +1565,7 @@ im__open_temp( void )
|
||||
if( im_add_close_callback( disc,
|
||||
(im_callback_fn) unlink, disc->filename, NULL ) ) {
|
||||
im_close( disc );
|
||||
unlink( name );
|
||||
g_unlink( name );
|
||||
}
|
||||
|
||||
return( disc );
|
||||
|
Loading…
Reference in New Issue
Block a user