add magic "-" stdin filename
this almost works! $ vips invert - x.jpg < k2.jpg
This commit is contained in:
parent
3a2bebdffb
commit
442720a0a1
@ -621,6 +621,55 @@ vips_foreign_find_load_buffer( const void *data, size_t size )
|
||||
return( G_OBJECT_CLASS_NAME( load_class ) );
|
||||
}
|
||||
|
||||
/* Can this VipsForeign open this stream?
|
||||
*/
|
||||
static void *
|
||||
vips_foreign_find_load_stream_sub( void *item, void *a, void *b )
|
||||
{
|
||||
VipsForeignLoadClass *load_class = VIPS_FOREIGN_LOAD_CLASS( item );
|
||||
VipsStreamInput *input = VIPS_STREAM_INPUT( a );
|
||||
|
||||
if( load_class->is_a_stream &&
|
||||
load_class->is_a_stream( input ) )
|
||||
return( load_class );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_foreign_find_load_stream:
|
||||
* @input: stream to load from
|
||||
*
|
||||
* Searches for an operation you could use to load a stream. To see the
|
||||
* range of buffer loaders supported by your vips, try something like:
|
||||
*
|
||||
* vips -l | grep load_stream
|
||||
*
|
||||
* See also: vips_image_new_from_stream().
|
||||
*
|
||||
* Returns: (transfer none): the name of an operation on success, %NULL on
|
||||
* error.
|
||||
*/
|
||||
const char *
|
||||
vips_foreign_find_load_stream( VipsStreamInput *input )
|
||||
{
|
||||
VipsForeignLoadClass *load_class;
|
||||
|
||||
if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map(
|
||||
"VipsForeignLoad",
|
||||
vips_foreign_find_load_stream_sub,
|
||||
input, NULL )) ) {
|
||||
vips_error( "VipsForeignLoad",
|
||||
"%s", _( "stream is not in a known format" ) );
|
||||
(void) vips_stream_input_rewind( input );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
(void) vips_stream_input_rewind( input );
|
||||
|
||||
return( G_OBJECT_CLASS_NAME( load_class ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_foreign_is_a:
|
||||
* @loader: name of loader to use for test
|
||||
|
@ -134,9 +134,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
#define DEBUG_VERBOSE
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -1216,6 +1216,10 @@ vips__jpeg_read_stream( VipsStreamInput *input, VipsImage *out,
|
||||
if( vips__jpeg_read( jpeg, out, header_only ) )
|
||||
return( -1 );
|
||||
|
||||
/* We've read the header ... it's pixel decode from now on.
|
||||
vips_stream_input_decode( input );
|
||||
*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
#define DEBUG_VERBOSE
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -359,6 +359,8 @@ vips_foreign_load_jpeg_stream_load( VipsForeignLoad *load )
|
||||
static gboolean
|
||||
vips_foreign_load_jpeg_stream_is_a( VipsStreamInput *input )
|
||||
{
|
||||
printf( "vips_foreign_load_jpeg_stream_is_a:\n" );
|
||||
|
||||
return( vips__isjpeg_stream( input ) );
|
||||
}
|
||||
|
||||
|
@ -240,6 +240,7 @@ GType vips_foreign_load_get_type(void);
|
||||
|
||||
const char *vips_foreign_find_load( const char *filename );
|
||||
const char *vips_foreign_find_load_buffer( const void *data, size_t size );
|
||||
const char *vips_foreign_find_load_stream( VipsStreamInput *stream );
|
||||
|
||||
VipsForeignFlags vips_foreign_flags( const char *loader, const char *filename );
|
||||
gboolean vips_foreign_is_a( const char *loader, const char *filename );
|
||||
|
@ -450,13 +450,16 @@ VipsImage *vips_image_new_from_memory_copy( const void *data, size_t size,
|
||||
VipsImage *vips_image_new_from_buffer( const void *buf, size_t len,
|
||||
const char *option_string, ... )
|
||||
__attribute__((sentinel));
|
||||
VipsImage *vips_image_new_from_stream( VipsStreamInput *input,
|
||||
const char *option_string, ... ) __attribute__((sentinel));
|
||||
VipsImage *vips_image_new_matrix( int width, int height );
|
||||
VipsImage *vips_image_new_matrixv( int width, int height, ... );
|
||||
VipsImage *vips_image_new_matrix_from_array( int width, int height,
|
||||
const double *array, int size );
|
||||
VipsImage *vips_image_matrix_from_array( int width, int height,
|
||||
const double *array, int size );
|
||||
VipsImage *vips_image_new_from_image( VipsImage *image, const double *c, int n );
|
||||
VipsImage *vips_image_new_from_image( VipsImage *image,
|
||||
const double *c, int n );
|
||||
VipsImage *vips_image_new_from_image1( VipsImage *image, double c );
|
||||
|
||||
void vips_image_set_delete_on_close( VipsImage *image,
|
||||
|
@ -2167,6 +2167,48 @@ vips_image_new_from_buffer( const void *buf, size_t len,
|
||||
return( out );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_new_from_stream: (constructor)
|
||||
* @input: (transfer none): stream to fetch image from
|
||||
* @option_string: set of extra options as a string
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Loads an image from the formatted stream @input,
|
||||
* loader recommended by vips_foreign_find_load_stream().
|
||||
*
|
||||
* Load options may be given in @option_string as "[name=value,...]" or given as
|
||||
* a NULL-terminated list of name-value pairs at the end of the arguments.
|
||||
* Options given in the function call override options given in the string.
|
||||
*
|
||||
* See also: vips_image_write_to_buffer().
|
||||
*
|
||||
* Returns: (transfer full): the new #VipsImage, or %NULL on error.
|
||||
*/
|
||||
VipsImage *
|
||||
vips_image_new_from_stream( VipsStreamInput *input,
|
||||
const char *option_string, ... )
|
||||
{
|
||||
const char *operation_name;
|
||||
va_list ap;
|
||||
int result;
|
||||
VipsImage *out;
|
||||
|
||||
vips_check_init();
|
||||
|
||||
if( !(operation_name = vips_foreign_find_load_stream( input )) )
|
||||
return( NULL );
|
||||
|
||||
va_start( ap, option_string );
|
||||
result = vips_call_split_option_string( operation_name,
|
||||
option_string, ap, input, &out );
|
||||
va_end( ap );
|
||||
|
||||
if( result )
|
||||
return( NULL );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_new_matrix: (constructor)
|
||||
* @width: image width
|
||||
|
@ -1899,16 +1899,35 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
|
||||
/* Read the filename.
|
||||
*/
|
||||
if( flags & (VIPS_OPERATION_SEQUENTIAL_UNBUFFERED |
|
||||
VIPS_OPERATION_SEQUENTIAL) )
|
||||
if( flags &
|
||||
(VIPS_OPERATION_SEQUENTIAL_UNBUFFERED |
|
||||
VIPS_OPERATION_SEQUENTIAL) )
|
||||
access = VIPS_ACCESS_SEQUENTIAL;
|
||||
else
|
||||
access = VIPS_ACCESS_RANDOM;
|
||||
|
||||
if( !(out = vips_image_new_from_file( value,
|
||||
"access", access,
|
||||
NULL )) )
|
||||
return( -1 );
|
||||
/* The special filename "-" means stdin.
|
||||
*/
|
||||
if( strcmp( value, "-" ) == 0 ) {
|
||||
VipsStreamInput *input;
|
||||
|
||||
if( !(input =
|
||||
vips_stream_input_new_from_descriptor( 0 )) )
|
||||
return( -1 );
|
||||
if( !(out = vips_image_new_from_stream( input, "",
|
||||
"access", access,
|
||||
NULL )) ) {
|
||||
VIPS_UNREF( input );
|
||||
return( -1 );
|
||||
}
|
||||
VIPS_UNREF( input );
|
||||
}
|
||||
else {
|
||||
if( !(out = vips_image_new_from_file( value,
|
||||
"access", access,
|
||||
NULL )) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_value_init( &gvalue, VIPS_TYPE_IMAGE );
|
||||
g_value_set_object( &gvalue, out );
|
||||
|
@ -41,8 +41,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#define VIPS_DEBUG
|
||||
*/
|
||||
#define VIPS_DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -243,6 +243,8 @@ vips_stream_input_read_real( VipsStreamInput *input,
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( input );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_read_real:\n" );
|
||||
|
||||
if( input->blob ) {
|
||||
VipsArea *area = (VipsArea *) input->blob;
|
||||
ssize_t available = VIPS_MIN( length,
|
||||
@ -255,7 +257,7 @@ vips_stream_input_read_real( VipsStreamInput *input,
|
||||
|
||||
return( available );
|
||||
}
|
||||
else if( stream->descriptor ) {
|
||||
else if( stream->descriptor != -1 ) {
|
||||
return( read( stream->descriptor, buffer, length ) );
|
||||
}
|
||||
else {
|
||||
@ -269,6 +271,8 @@ vips_stream_input_rewind_real( VipsStreamInput *input )
|
||||
{
|
||||
VipsStream *stream = VIPS_STREAM( input );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_rewind_real:\n" );
|
||||
|
||||
if( input->decode ) {
|
||||
vips_error( STREAM_NAME( stream ),
|
||||
"%s", _( "can't rewind after decode begins" ) );
|
||||
@ -279,6 +283,9 @@ vips_stream_input_rewind_real( VipsStreamInput *input )
|
||||
stream->descriptor != -1 ) {
|
||||
off_t new_pos;
|
||||
|
||||
VIPS_DEBUG_MSG( " rewinding desriptor %d\n",
|
||||
stream->descriptor );
|
||||
|
||||
new_pos = lseek( stream->descriptor, 0, SEEK_SET );
|
||||
if( new_pos == -1 ) {
|
||||
vips_error_system( errno, STREAM_NAME( stream ),
|
||||
@ -468,12 +475,14 @@ vips_stream_input_read( VipsStreamInput *input,
|
||||
|
||||
ssize_t bytes_read;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_read:\n" );
|
||||
|
||||
bytes_read = 0;
|
||||
|
||||
/* Are we serving from header_bytes? Get what we can from there.
|
||||
*/
|
||||
if( input->header_bytes &&
|
||||
input->header_bytes->len < input->read_position ) {
|
||||
input->read_position < input->header_bytes->len ) {
|
||||
ssize_t available;
|
||||
|
||||
available = VIPS_MIN( length,
|
||||
@ -485,19 +494,21 @@ vips_stream_input_read( VipsStreamInput *input,
|
||||
buffer += available;
|
||||
length -= available;
|
||||
bytes_read += available;
|
||||
|
||||
VIPS_DEBUG_MSG( " %zd bytes from cache\n", available );
|
||||
}
|
||||
|
||||
/* Any more bytes required? Call the read() method.
|
||||
*/
|
||||
if( length > 0 ) {
|
||||
ssize_t read;
|
||||
ssize_t n;
|
||||
|
||||
if( (read = class->read( input, buffer, length )) == -1 ) {
|
||||
if( (n = class->read( input, buffer, length )) == -1 ) {
|
||||
vips_error_system( errno, STREAM_NAME( input ),
|
||||
"%s", _( "read error" ) );
|
||||
return( -1 );
|
||||
}
|
||||
if( read == 0 )
|
||||
if( n == 0 )
|
||||
input->eof = TRUE;
|
||||
|
||||
/* If we're not rewindable, we need to save header bytes for
|
||||
@ -506,14 +517,18 @@ vips_stream_input_read( VipsStreamInput *input,
|
||||
if( input->header_bytes &&
|
||||
!input->rewindable &&
|
||||
!input->decode &&
|
||||
read > 0 )
|
||||
n > 0 )
|
||||
g_byte_array_append( input->header_bytes,
|
||||
buffer, read );
|
||||
buffer, n );
|
||||
|
||||
input->read_position += read;
|
||||
bytes_read += read;
|
||||
input->read_position += n;
|
||||
bytes_read += n;
|
||||
|
||||
VIPS_DEBUG_MSG( " %zd bytes from read()\n", n );
|
||||
}
|
||||
|
||||
VIPS_DEBUG_MSG( " %zd bytes total\n", bytes_read );
|
||||
|
||||
return( bytes_read );
|
||||
}
|
||||
|
||||
@ -522,18 +537,24 @@ vips_stream_input_rewind( VipsStreamInput *input )
|
||||
{
|
||||
VipsStreamInputClass *class = VIPS_STREAM_INPUT_GET_CLASS( input );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_rewind:\n" );
|
||||
|
||||
return( class->rewind( input ) );
|
||||
}
|
||||
|
||||
gboolean
|
||||
vips_stream_input_eof( VipsStreamInput *input )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_eof:\n" );
|
||||
|
||||
return( input->eof );
|
||||
}
|
||||
|
||||
void
|
||||
vips_stream_input_decode( VipsStreamInput *input )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_decode:\n" );
|
||||
|
||||
input->decode = TRUE;
|
||||
VIPS_FREEF( g_byte_array_unref, input->header_bytes );
|
||||
VIPS_FREEF( g_byte_array_unref, input->sniff );
|
||||
@ -548,20 +569,20 @@ vips_stream_input_decode( VipsStreamInput *input )
|
||||
unsigned char *
|
||||
vips_stream_input_sniff( VipsStreamInput *input, size_t length )
|
||||
{
|
||||
ssize_t read;
|
||||
ssize_t n;
|
||||
unsigned char *q;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_stream_input_sniff: %zd bytes\n", length );
|
||||
|
||||
if( vips_stream_input_rewind( input ) )
|
||||
return( NULL );
|
||||
|
||||
g_byte_array_set_size( input->sniff, length );
|
||||
|
||||
for( q = input->sniff->data; length > 0; length -= read, q += read ) {
|
||||
read = vips_stream_input_read( input, q, length );
|
||||
if( read == -1 ||
|
||||
read == 0 )
|
||||
for( q = input->sniff->data; length > 0; length -= n, q += n )
|
||||
if( (n = vips_stream_input_read( input, q, length )) == -1 ||
|
||||
n == 0 )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( input->sniff->data );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user