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:
parent
ad822109d4
commit
6c1d7db31b
@ -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" ) );
|
||||
|
@ -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 );
|
||||
|
@ -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*/
|
||||
|
||||
/**
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user