160 lines
3.4 KiB
C
160 lines
3.4 KiB
C
/* Test stream*u.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <vips/vips.h>
|
|
|
|
typedef struct _MyInput {
|
|
const char *filename;
|
|
unsigned char *contents;
|
|
size_t length;
|
|
size_t read_position;
|
|
} MyInput;
|
|
|
|
typedef struct _MyOutput {
|
|
const char *filename;
|
|
int fd;
|
|
} MyOutput;
|
|
|
|
static gint64
|
|
read_cb( VipsSourceCustom *source_custom,
|
|
void *buffer, gint64 length, MyInput *my_input )
|
|
{
|
|
gint64 bytes_read = VIPS_MIN( length,
|
|
my_input->length - my_input->read_position );
|
|
|
|
/*
|
|
printf( "read_cb: buffer = 0x%p, length = %zd\n", buffer, length );
|
|
*/
|
|
|
|
memcpy( buffer,
|
|
my_input->contents + my_input->read_position, bytes_read );
|
|
my_input->read_position += bytes_read;
|
|
|
|
return( bytes_read );
|
|
}
|
|
|
|
static gint64
|
|
seek_cb( VipsSourceCustom *source_custom,
|
|
gint64 offset, int whence, MyInput *my_input )
|
|
{
|
|
gint64 new_pos;
|
|
|
|
/*
|
|
printf( "seek_cb: offset = %zd, whence = %d\n", offset, whence );
|
|
*/
|
|
|
|
switch( whence ) {
|
|
case SEEK_SET:
|
|
new_pos = offset;
|
|
break;
|
|
|
|
case SEEK_CUR:
|
|
new_pos = my_input->read_position + offset;
|
|
break;
|
|
|
|
case SEEK_END:
|
|
new_pos = my_input->length + offset;
|
|
break;
|
|
|
|
default:
|
|
vips_error( "demo", "%s", "bad 'whence'" );
|
|
return( -1 );
|
|
}
|
|
|
|
my_input->read_position = VIPS_CLIP( 0, new_pos, my_input->length );
|
|
|
|
return( my_input->read_position );
|
|
}
|
|
|
|
static gint64
|
|
write_cb( VipsTargetCustom *target_custom,
|
|
const void *data, gint64 length, MyOutput *my_output )
|
|
{
|
|
gint64 bytes_written;
|
|
|
|
/*
|
|
printf( "write_cb: data = 0x%p, length = %zd\n", data, length );
|
|
*/
|
|
|
|
bytes_written = write( my_output->fd, data, length );
|
|
|
|
return( bytes_written );
|
|
}
|
|
|
|
static void
|
|
finish_cb( VipsTargetCustom *target_custom, MyOutput *my_output )
|
|
{
|
|
/*
|
|
printf( "finish_cb:\n" );
|
|
*/
|
|
|
|
close( my_output->fd );
|
|
my_output->fd = -1;
|
|
}
|
|
|
|
int
|
|
main( int argc, char **argv )
|
|
{
|
|
MyInput my_input;
|
|
MyOutput my_output;
|
|
VipsSourceCustom *source_custom;
|
|
VipsTargetCustom *target_custom;
|
|
VipsImage *image;
|
|
|
|
if( VIPS_INIT( argv[0] ) )
|
|
return( -1 );
|
|
|
|
if( argc != 3 )
|
|
vips_error_exit( "usage: %s in-file out-file.png", argv[0] );
|
|
|
|
my_input.filename = argv[1];
|
|
my_input.contents = NULL;
|
|
my_input.length = 0;
|
|
my_input.read_position = 0;
|
|
|
|
if( !g_file_get_contents( my_input.filename,
|
|
(char **) &my_input.contents, &my_input.length, NULL ) )
|
|
vips_error_exit( "unable to load from %s", my_input.filename );
|
|
|
|
source_custom = vips_source_custom_new();
|
|
g_signal_connect( source_custom, "seek",
|
|
G_CALLBACK( seek_cb ), &my_input );
|
|
g_signal_connect( source_custom, "read",
|
|
G_CALLBACK( read_cb ), &my_input );
|
|
|
|
if( !(image = vips_image_new_from_source(
|
|
VIPS_SOURCE( source_custom ), "",
|
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
|
NULL )) )
|
|
vips_error_exit( NULL );
|
|
|
|
my_output.filename = argv[2];
|
|
my_output.fd = -1;
|
|
|
|
if( (my_output.fd = vips__open( my_output.filename,
|
|
O_WRONLY | O_CREAT | O_TRUNC, 0644 )) == -1 )
|
|
vips_error_exit( "unable to save to %s", my_output.filename );
|
|
|
|
target_custom = vips_target_custom_new();
|
|
g_signal_connect( target_custom, "write",
|
|
G_CALLBACK( write_cb ), &my_output );
|
|
g_signal_connect( target_custom, "finish",
|
|
G_CALLBACK( finish_cb ), &my_output );
|
|
|
|
if( vips_image_write_to_target( image, ".png",
|
|
VIPS_TARGET( target_custom ), NULL ) )
|
|
vips_error_exit( NULL );
|
|
|
|
VIPS_UNREF( image );
|
|
VIPS_UNREF( source_custom );
|
|
VIPS_UNREF( target_custom );
|
|
g_free( my_input.contents );
|
|
|
|
return( 0 );
|
|
}
|