remove old jpeg load stuff

it's just stream now

works on buffer, but seems to fail on

	vipsheader йцук.jpg

curiously
This commit is contained in:
John Cupitt 2019-10-11 09:43:12 +01:00
parent ad822109d4
commit 6c1d7db31b
7 changed files with 240 additions and 470 deletions

View File

@ -111,9 +111,18 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
}
#ifdef HAVE_JPEG
if( vips__jpeg_read_file( filename, out,
header_only, shrink, fail_on_warn, FALSE ) )
{
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( -1 );
if( vips__jpeg_read_stream( input, out,
header_only, shrink, fail_on_warn, FALSE ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
}
#else
vips_error( "im_jpeg2vips",
"%s", _( "no JPEG support in your libvips" ) );

View File

@ -169,10 +169,6 @@ typedef struct _ReadJpeg {
*/
gboolean fail;
/* Used for file input only.
*/
char *filename;
struct jpeg_decompress_struct cinfo;
ErrorManager eman;
gboolean invert_pels;
@ -193,113 +189,12 @@ typedef struct _ReadJpeg {
int output_width;
int output_height;
/* If we close and reopen, save the ftell point here.
*/
long seek_position;
/* The memory area we read from.
*/
const void *buf;
size_t len;
/* The stream we read from.
*/
VipsStreamInput *input;
} ReadJpeg;
/* Private struct for memory input.
*/
typedef struct {
/* Public jpeg fields.
*/
struct jpeg_source_mgr pub;
/* Private stuff during read.
*/
const JOCTET *buf;
size_t len;
} InputBuffer;
static void
init_source( j_decompress_ptr cinfo )
{
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* We fill the buffer on readjpeg_buffer(), so this will only be called if
* libjpeg tries to read beyond the buffer.
*/
static boolean
fill_input_buffer( j_decompress_ptr cinfo )
{
static const JOCTET eoi_buffer[4] = {
(JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0
};
InputBuffer *src = (InputBuffer *) cinfo->src;
WARNMS( cinfo, JWRN_JPEG_EOF );
src->pub.next_input_byte = eoi_buffer;
src->pub.bytes_in_buffer = 2;
return( TRUE );
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
static void
skip_input_data( j_decompress_ptr cinfo, long num_bytes )
{
InputBuffer *src = (InputBuffer *) cinfo->src;
if( num_bytes > 0 ) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) (*src->pub.fill_input_buffer) (cinfo);
/* note we assume that fill_input_buffer will never
* return FALSE, so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
static void
term_source( j_decompress_ptr cinfo )
{
}
#define STREAM_BUFFER_SIZE (4096)
/* Private struct for stream input.
@ -314,18 +209,18 @@ typedef struct {
VipsStreamInput *input;
unsigned char buf[STREAM_BUFFER_SIZE];
} InputSource;
} Source;
static void
stream_init_source( j_decompress_ptr cinfo )
{
InputSource *source = (InputSource *) cinfo->src;
Source *src = (Source *) cinfo->src;
/* Start off empty ... libjpeg will call fill_input_buffer to get the
* first bytes.
*/
source->pub.next_input_byte = source->buf;
source->pub.bytes_in_buffer = 0;
src->pub.next_input_byte = src->buf;
src->pub.bytes_in_buffer = 0;
}
/* Fill the input buffer --- called whenever buffer is emptied.
@ -337,19 +232,19 @@ stream_fill_input_buffer( j_decompress_ptr cinfo )
(JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0
};
InputSource *source = (InputSource *) cinfo->src;
Source *src = (Source *) cinfo->src;
size_t read;
if( (read = vips_stream_input_read( source->input,
source->buf, STREAM_BUFFER_SIZE )) == -1 ) {
WARNMS( cinfo, JWRN_JPEG_EOF );
source->pub.next_input_byte = eoi_buffer;
source->pub.bytes_in_buffer = 2;
if( (read = vips_stream_input_read( src->input,
src->buf, STREAM_BUFFER_SIZE )) > 0 ) {
src->pub.next_input_byte = src->buf;
src->pub.bytes_in_buffer = read;
}
else {
source->pub.next_input_byte = source->buf;
source->pub.bytes_in_buffer = read;
WARNMS( cinfo, JWRN_JPEG_EOF );
src->pub.next_input_byte = eoi_buffer;
src->pub.bytes_in_buffer = 2;
}
return( TRUE );
@ -360,41 +255,9 @@ readjpeg_open_input( ReadJpeg *jpeg )
{
j_decompress_ptr cinfo = &jpeg->cinfo;
if( jpeg->filename &&
!jpeg->eman.fp ) {
if( !(jpeg->eman.fp =
vips__file_open_read( jpeg->filename, NULL, FALSE )) )
return( -1 );
jpeg_stdio_src( cinfo, jpeg->eman.fp );
if( jpeg->seek_position != -1 )
fseek( jpeg->eman.fp, jpeg->seek_position, SEEK_SET );
}
if( jpeg->buf &&
!cinfo->src ) {
InputBuffer *src;
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small)(
(j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof( InputBuffer ) );
src = (InputBuffer *) cinfo->src;
src->buf = jpeg->buf;
src->len = jpeg->len;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = term_source;
src->pub.bytes_in_buffer = jpeg->len;
src->pub.next_input_byte = jpeg->buf;
}
if( jpeg->input &&
!cinfo->src ) {
InputSource *src;
Source *src;
if( vips_stream_input_rewind( jpeg->input ) )
return( -1 );
@ -402,15 +265,13 @@ readjpeg_open_input( ReadJpeg *jpeg )
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small)(
(j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof( InputSource ) );
sizeof( Source ) );
src = (InputSource *) cinfo->src;
src = (Source *) cinfo->src;
src->input = jpeg->input;
src->pub.init_source = stream_init_source;
src->pub.fill_input_buffer = stream_fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = term_source;
src->pub.bytes_in_buffer = 0;
src->pub.next_input_byte = src->buf;
}
@ -418,21 +279,6 @@ readjpeg_open_input( ReadJpeg *jpeg )
return( 0 );
}
/* This can be called many times.
*/
static void
readjpeg_close_input( ReadJpeg *jpeg )
{
#ifdef DEBUG
printf( "readjpeg_close_input:\n" );
#endif /*DEBUG*/
if( jpeg->eman.fp ) {
jpeg->seek_position = ftell( jpeg->eman.fp );
VIPS_FREEF( fclose, jpeg->eman.fp );
}
}
/* This can be called many times.
*/
static int
@ -448,8 +294,6 @@ readjpeg_free( ReadJpeg *jpeg )
jpeg->eman.pub.num_warnings = 0;
}
readjpeg_close_input( jpeg );
/* Don't call jpeg_finish_decompress(). It just checks the tail of the
* file and who cares about that. All mem is freed in
* jpeg_destroy_decompress().
@ -459,7 +303,7 @@ readjpeg_free( ReadJpeg *jpeg )
*/
jpeg_destroy_decompress( &jpeg->cinfo );
VIPS_FREE( jpeg->filename );
VIPS_UNREF( jpeg->input );
return( 0 );
}
@ -470,34 +314,25 @@ readjpeg_close_cb( VipsObject *object, ReadJpeg *jpeg )
(void) readjpeg_free( jpeg );
}
static void
readjpeg_minimise_cb( VipsObject *object, ReadJpeg *jpeg )
{
#ifdef DEBUG
printf( "readjpeg_minimise_cb:\n" );
#endif /*DEBUG*/
readjpeg_close_input( jpeg );
}
static ReadJpeg *
readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean autorotate )
readjpeg_new( VipsStreamInput *input, VipsImage *out,
int shrink, gboolean fail, gboolean autorotate )
{
ReadJpeg *jpeg;
if( !(jpeg = VIPS_NEW( out, ReadJpeg )) )
return( NULL );
jpeg->input = input;
g_object_ref( input );
jpeg->shrink = shrink;
jpeg->fail = fail;
jpeg->filename = NULL;
jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub );
jpeg->eman.pub.error_exit = vips__new_error_exit;
jpeg->eman.pub.output_message = vips__new_output_message;
jpeg->eman.fp = NULL;
jpeg->y_pos = 0;
jpeg->autorotate = autorotate;
jpeg->seek_position = -1;
/* This is used by the error handlers to signal invalidate on the
* output image.
@ -514,24 +349,10 @@ readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean autorotate )
g_signal_connect( out, "close",
G_CALLBACK( readjpeg_close_cb ), jpeg );
g_signal_connect( out, "minimise",
G_CALLBACK( readjpeg_minimise_cb ), jpeg );
return( jpeg );
}
/* Set input to a file.
*/
static int
readjpeg_file( ReadJpeg *jpeg, const char *filename )
{
jpeg->filename = g_strdup( filename );
if( readjpeg_open_input( jpeg ) )
return( -1 );
return( 0 );
}
static const char *
find_chroma_subsample( struct jpeg_decompress_struct *cinfo )
{
@ -974,11 +795,6 @@ read_jpeg_generate( VipsRegion *or,
jpeg->y_pos += 1;
}
/* Shut down the input early if we can.
*/
if( jpeg->y_pos >= or->im->Ysize )
readjpeg_close_input( jpeg );
VIPS_GATE_STOP( "read_jpeg_generate: work" );
return( 0 );
@ -1063,8 +879,6 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out )
return( 0 );
}
/* Read the jpeg from file or buffer.
*/
static int
vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only )
{
@ -1120,103 +934,18 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only )
return( 0 );
}
/* Read a JPEG file into a VIPS image.
*/
int
vips__jpeg_read_file( const char *filename, VipsImage *out,
gboolean header_only, int shrink, gboolean fail,
gboolean autorotate )
{
ReadJpeg *jpeg;
if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) )
return( -1 );
/* Here for longjmp() from vips__new_error_exit() during startup.
*/
if( setjmp( jpeg->eman.jmp ) )
return( -1 );
/* Set input to file.
*/
if( readjpeg_file( jpeg, filename ) )
return( -1 );
if( vips__jpeg_read( jpeg, out, header_only ) )
return( -1 );
VIPS_SETSTR( out->filename, filename );
/* We can kill off the decompress early if this is just a header read.
* This saves an fd during read.
*/
if( header_only )
readjpeg_free( jpeg );
return( 0 );
}
int
vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
gboolean header_only, int shrink, int fail, gboolean autorotate )
{
ReadJpeg *jpeg;
if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) )
return( -1 );
if( setjmp( jpeg->eman.jmp ) )
return( -1 );
jpeg->buf = buf;
jpeg->len = len;
if( readjpeg_open_input( jpeg ) )
return( -1 );
if( vips__jpeg_read( jpeg, out, header_only ) )
return( -1 );
return( 0 );
}
int
vips__isjpeg_buffer( const void *buf, size_t len )
{
const guchar *str = (const 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 ) == 2 &&
vips__isjpeg_buffer( buf, 2 ) )
return( 1 );
return( 0 );
}
int
vips__jpeg_read_stream( VipsStreamInput *input, VipsImage *out,
gboolean header_only, int shrink, int fail, gboolean autorotate )
{
ReadJpeg *jpeg;
if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) )
if( !(jpeg = readjpeg_new( input, out, shrink, fail, autorotate )) )
return( -1 );
if( setjmp( jpeg->eman.jmp ) )
return( -1 );
jpeg->input = input;
if( readjpeg_open_input( jpeg ) )
return( -1 );
@ -1232,7 +961,8 @@ vips__isjpeg_stream( VipsStreamInput *input )
const unsigned char *p;
if( (p = vips_stream_input_sniff( input, 2 )) &&
vips__isjpeg_buffer( p, 2 ) )
p[0] == 0xff &&
p[1] == 0xd8 )
return( 1 );
return( 0 );

View File

@ -155,171 +155,9 @@ vips_foreign_load_jpeg_init( VipsForeignLoadJpeg *jpeg )
jpeg->shrink = 1;
}
typedef struct _VipsForeignLoadJpegFile {
VipsForeignLoadJpeg parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadJpegFile;
typedef VipsForeignLoadJpegClass VipsForeignLoadJpegFileClass;
G_DEFINE_TYPE( VipsForeignLoadJpegFile, vips_foreign_load_jpeg_file,
vips_foreign_load_jpeg_get_type() );
static gboolean
vips_foreign_load_jpeg_file_is_a( const char *filename )
{
return( vips__isjpeg( filename ) );
}
static int
vips_foreign_load_jpeg_file_header( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
if( vips__jpeg_read_file( file->filename, load->out,
TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_jpeg_file_load( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
if( vips__jpeg_read_file( file->filename, load->real,
FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_jpeg_file_class_init( VipsForeignLoadJpegFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "jpegload";
object_class->description = _( "load jpeg from file" );
foreign_class->suffs = vips__jpeg_suffs;
/* We are fast at is_a(), so high priority.
*/
foreign_class->priority = 50;
load_class->is_a = vips_foreign_load_jpeg_file_is_a;
load_class->header = vips_foreign_load_jpeg_file_header;
load_class->load = vips_foreign_load_jpeg_file_load;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadJpegFile, filename ),
NULL );
}
static void
vips_foreign_load_jpeg_file_init( VipsForeignLoadJpegFile *file )
{
}
typedef struct _VipsForeignLoadJpegBuffer {
VipsForeignLoadJpeg parent_object;
/* Load from a buffer.
*/
VipsArea *buf;
} VipsForeignLoadJpegBuffer;
typedef VipsForeignLoadJpegClass VipsForeignLoadJpegBufferClass;
G_DEFINE_TYPE( VipsForeignLoadJpegBuffer, vips_foreign_load_jpeg_buffer,
vips_foreign_load_jpeg_get_type() );
static int
vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
load->out, TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
load->real, FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) )
return( -1 );
return( 0 );
}
static gboolean
vips_foreign_load_jpeg_buffer_is_a( const void *buf, size_t len )
{
return( vips__isjpeg_buffer( buf, len ) );
}
static void
vips_foreign_load_jpeg_buffer_class_init(
VipsForeignLoadJpegBufferClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
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;
VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ),
_( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadJpegBuffer, buf ),
VIPS_TYPE_BLOB );
}
static void
vips_foreign_load_jpeg_buffer_init( VipsForeignLoadJpegBuffer *buffer )
{
}
typedef struct _VipsForeignLoadJpegStream {
VipsForeignLoadJpeg parent_object;
/* Load from a buffer.
*/
VipsStreamInput *input;
} VipsForeignLoadJpegStream;
@ -395,6 +233,206 @@ vips_foreign_load_jpeg_stream_init( VipsForeignLoadJpegStream *stream )
{
}
typedef struct _VipsForeignLoadJpegFile {
VipsForeignLoadJpeg parent_object;
char *filename;
} VipsForeignLoadJpegFile;
typedef VipsForeignLoadJpegClass VipsForeignLoadJpegFileClass;
G_DEFINE_TYPE( VipsForeignLoadJpegFile, vips_foreign_load_jpeg_file,
vips_foreign_load_jpeg_get_type() );
static gboolean
vips_foreign_load_jpeg_file_is_a( const char *filename )
{
VipsStreamInput *input;
gboolean result;
if( !(input = vips_stream_input_new_from_filename( filename )) )
return( FALSE );
result = vips__isjpeg_stream( input );
VIPS_UNREF( input );
return( result );
}
static int
vips_foreign_load_jpeg_file_header( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_filename( file->filename )) )
return( -1 );
if( vips__jpeg_read_stream( input, load->out,
TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static int
vips_foreign_load_jpeg_file_load( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_filename( file->filename )) )
return( -1 );
if( vips__jpeg_read_stream( input, load->real,
FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static void
vips_foreign_load_jpeg_file_class_init( VipsForeignLoadJpegFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "jpegload";
object_class->description = _( "load jpeg from file" );
foreign_class->suffs = vips__jpeg_suffs;
/* We are fast at is_a(), so high priority.
*/
foreign_class->priority = 50;
load_class->is_a = vips_foreign_load_jpeg_file_is_a;
load_class->header = vips_foreign_load_jpeg_file_header;
load_class->load = vips_foreign_load_jpeg_file_load;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadJpegFile, filename ),
NULL );
}
static void
vips_foreign_load_jpeg_file_init( VipsForeignLoadJpegFile *file )
{
}
typedef struct _VipsForeignLoadJpegBuffer {
VipsForeignLoadJpeg parent_object;
VipsBlob *blob;
} VipsForeignLoadJpegBuffer;
typedef VipsForeignLoadJpegClass VipsForeignLoadJpegBufferClass;
G_DEFINE_TYPE( VipsForeignLoadJpegBuffer, vips_foreign_load_jpeg_buffer,
vips_foreign_load_jpeg_get_type() );
static gboolean
vips_foreign_load_jpeg_buffer_is_a( const void *buf, size_t len )
{
VipsStreamInput *input;
gboolean result;
if( !(input = vips_stream_input_new_from_memory( buf, len )) )
return( FALSE );
result = vips__isjpeg_stream( input );
VIPS_UNREF( input );
return( result );
}
static int
vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_blob( buffer->blob )) )
return( -1 );
if( vips__jpeg_read_stream( input, load->out,
TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static int
vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load;
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
VipsStreamInput *input;
if( !(input = vips_stream_input_new_from_blob( buffer->blob )) )
return( -1 );
if( vips__jpeg_read_stream( input, load->real,
FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static void
vips_foreign_load_jpeg_buffer_class_init(
VipsForeignLoadJpegBufferClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
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;
VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ),
_( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadJpegBuffer, blob ),
VIPS_TYPE_BLOB );
}
static void
vips_foreign_load_jpeg_buffer_init( VipsForeignLoadJpegBuffer *buffer )
{
}
#endif /*HAVE_JPEG*/
/**

View File

@ -185,13 +185,6 @@ int vips__jpeg_write_buffer( VipsImage *in,
gboolean overshoot_deringing, gboolean optimize_scans,
int quant_table );
int vips__isjpeg_buffer( const 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 autorotate );
int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
gboolean header_only, int shrink, int fail, gboolean autorotate );
int vips__jpeg_read_stream( VipsStreamInput *input, VipsImage *out,
gboolean header_only, int shrink, int fail, gboolean autorotate );
int vips__isjpeg_stream( VipsStreamInput *input );

View File

@ -169,7 +169,8 @@ GType vips_stream_input_get_type( void );
VipsStreamInput *vips_stream_input_new_from_descriptor( int descriptor );
VipsStreamInput *vips_stream_input_new_from_filename( const char *filename );
VipsStreamInput *vips_stream_input_new_from_blob( VipsBlob *blob );
VipsStreamInput *vips_stream_input_new_from_memory( void *data, size_t size );
VipsStreamInput *vips_stream_input_new_from_memory( const void *data,
size_t size );
ssize_t vips_stream_input_read( VipsStreamInput *input,
unsigned char *buffer, size_t length );
@ -217,8 +218,8 @@ typedef struct _VipsStreamOutputClass {
GType vips_stream_output_get_type( void );
VipsStreamOutput *vips_stream_output_new_to_descriptor( int descriptor );
VipsStreamOutput *vips_stream_output_new_to_filename( const char *filename );
VipsStreamOutput *vips_stream_output_new_from_descriptor( int descriptor );
VipsStreamOutput *vips_stream_output_new_from_filename( const char *filename );
int vips_stream_output_write( VipsStreamOutput *stream,
const unsigned char *buffer, size_t buffer_size );

View File

@ -253,7 +253,7 @@ vips_stream_input_read_real( VipsStreamInput *input,
if( available <= 0 )
return( 0 );
memcpy( buffer, area->data, available );
memcpy( buffer, area->data + input->read_position, available );
return( available );
}
@ -448,7 +448,7 @@ vips_stream_input_new_from_blob( VipsBlob *blob )
* Returns: a new #VipsStream
*/
VipsStreamInput *
vips_stream_input_new_from_memory( void *data, size_t size )
vips_stream_input_new_from_memory( const void *data, size_t size )
{
VipsStreamInput *stream;
VipsBlob *blob;

View File

@ -83,7 +83,6 @@ class TestColour:
assert_almost_equal_objects(before, after, threshold=10)
# test results from Bruce Lindbloom's calculator:
# http://www.brucelindbloom.com
def test_dE00(self):