basic webp load done
This commit is contained in:
parent
878c196341
commit
165e7c9717
@ -7,6 +7,7 @@
|
||||
- added vips_error_freeze() / vips_error_thaw()
|
||||
- used freeze() / thaw() to stop file format sniffers logging spurious errors
|
||||
- vipsthumbnail uses embedded jpg thumbnails if it can
|
||||
- added vips_webpload(), vips_webpload_buffer()
|
||||
|
||||
3/7/13 started 7.34.2
|
||||
- lower priority for Matlab load to reduce segvs from Mat_Open(), thanks
|
||||
|
@ -689,14 +689,14 @@ fi
|
||||
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS and VIPS_CXX_LIBS
|
||||
# sort includes to get longer, more specific dirs first
|
||||
# helps, for example, selecting graphicsmagick over imagemagick
|
||||
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $PANGOFT2_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
|
||||
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $PANGOFT2_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
|
||||
do
|
||||
echo $i
|
||||
done | sort -ru`
|
||||
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
|
||||
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
|
||||
VIPS_INCLUDES="$PNG_INCLUDES $TIFF_INCLUDES $ZIP_INCLUDES $JPEG_INCLUDES"
|
||||
VIPS_LIBS="$MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $ZIP_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
||||
VIPS_LIBS="$MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $ZIP_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
||||
|
||||
# we need this to generate paths in swig/python/setup.py.in
|
||||
AC_SUBST(top_srcdir)
|
||||
|
@ -32,9 +32,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
#define DEBUG_VERBOSE
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -43,20 +43,116 @@
|
||||
|
||||
#ifdef HAVE_LIBWEBP
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <webp/decode.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "webp.h"
|
||||
|
||||
/* How many bytes do we need to read from the start of the file to be able to
|
||||
* validate the header?
|
||||
*
|
||||
* This doesn't seem to be documented anywhere :-( guess a value.
|
||||
*/
|
||||
#define MINIMAL_HEADER (100)
|
||||
|
||||
/* What we track during a read.
|
||||
*/
|
||||
typedef struct {
|
||||
/* File source.
|
||||
*/
|
||||
char *filename;
|
||||
|
||||
/* Memory source.
|
||||
*/
|
||||
void *buf;
|
||||
size_t len;
|
||||
|
||||
/* Decoder config.
|
||||
*/
|
||||
WebPDecoderConfig config;
|
||||
|
||||
/* Incremental decoder state.
|
||||
*/
|
||||
WebPIDecoder *idec;
|
||||
} Read;
|
||||
|
||||
int
|
||||
vips__iswebp( const char *filename )
|
||||
{
|
||||
unsigned char buf[2];
|
||||
unsigned char header[MINIMAL_HEADER];
|
||||
|
||||
if( vips__get_bytes( filename, buf, 2 ) )
|
||||
if( (int) buf[0] == 0xff && (int) buf[1] == 0xd8 )
|
||||
return( 1 );
|
||||
if( vips__get_bytes( filename, header, MINIMAL_HEADER ) &&
|
||||
WebPGetInfo( header, MINIMAL_HEADER, NULL, NULL ) )
|
||||
return( 1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
read_free( Read *read )
|
||||
{
|
||||
VIPS_FREE( read->filename );
|
||||
VIPS_FREEF( WebPIDelete, read->idec );
|
||||
WebPFreeDecBuffer( &read->config.output );
|
||||
VIPS_FREE( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static Read *
|
||||
read_new( const char *filename, void *buf, size_t len )
|
||||
{
|
||||
Read *read;
|
||||
unsigned char header[MINIMAL_HEADER];
|
||||
|
||||
if( !(read = VIPS_NEW( NULL, Read )) )
|
||||
return( NULL );
|
||||
|
||||
read->filename = g_strdup( filename );
|
||||
read->buf = buf;
|
||||
read->len = len;
|
||||
read->idec = NULL;
|
||||
|
||||
WebPInitDecoderConfig( &read->config );
|
||||
if( filename ) {
|
||||
if( vips__get_bytes( filename, header, MINIMAL_HEADER ) &&
|
||||
WebPGetFeatures( header, MINIMAL_HEADER,
|
||||
&read->config.input ) != VP8_STATUS_OK ) {
|
||||
read_free( read );
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( WebPGetFeatures( read->buf, read->len,
|
||||
&read->config.input ) != VP8_STATUS_OK ) {
|
||||
read_free( read );
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if( read->config.input.has_alpha )
|
||||
read->config.output.colorspace = MODE_RGBA;
|
||||
else
|
||||
read->config.output.colorspace = MODE_RGB;
|
||||
read->config.options.use_threads = TRUE;
|
||||
|
||||
return( read );
|
||||
}
|
||||
|
||||
static int
|
||||
read_header( Read *read, VipsImage *out )
|
||||
{
|
||||
vips_image_init_fields( out,
|
||||
read->config.input.width, read->config.input.height,
|
||||
read->config.input.has_alpha ? 4 : 3,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_sRGB,
|
||||
1.0, 1.0 );
|
||||
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -64,7 +160,65 @@ vips__iswebp( const char *filename )
|
||||
int
|
||||
vips__webp_read_file_header( const char *filename, VipsImage *out )
|
||||
{
|
||||
printf( "vips__webp_read_file_header\n" );
|
||||
Read *read;
|
||||
|
||||
if( !(read = read_new( filename, NULL, 0 )) ) {
|
||||
vips_error( "webp2vips",
|
||||
_( "unable to open \"%s\"" ), filename );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( read_header( read, out ) )
|
||||
return( -1 );
|
||||
|
||||
read_free( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
typedef uint8_t *(*webp_reader)( const uint8_t* data, size_t data_size,
|
||||
uint8_t* output_buffer, size_t output_buffer_size,
|
||||
int output_stride );
|
||||
|
||||
static int
|
||||
read_image( Read *read, VipsImage *out )
|
||||
{
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( out ), 3 );
|
||||
char *data;
|
||||
unsigned int len;
|
||||
webp_reader reader;
|
||||
|
||||
/* libwebp makes streaming very hard. We have to read to a full memory
|
||||
* buffer, then copy to out.
|
||||
*/
|
||||
t[0] = vips_image_new_buffer();
|
||||
if( read_header( read, t[0] ) )
|
||||
return( -1 );
|
||||
if( vips_image_write_prepare( t[0] ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(data = vips__file_read_name( read->filename, NULL, &len )) )
|
||||
return( -1 );
|
||||
|
||||
if( t[0]->Bands == 3 )
|
||||
reader = WebPDecodeRGBInto;
|
||||
else
|
||||
reader = WebPDecodeRGBAInto;
|
||||
|
||||
if( !reader( (uint8_t *) data, len,
|
||||
VIPS_IMAGE_ADDR( t[0], 0, 0 ),
|
||||
VIPS_IMAGE_SIZEOF_IMAGE( t[0] ),
|
||||
VIPS_IMAGE_SIZEOF_LINE( t[0] ) ) ) {
|
||||
g_free( data );
|
||||
vips_error( "webp2vips", "%s", _( "unable to read pixels" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_free( data );
|
||||
|
||||
if( vips_image_write( t[0], out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -72,7 +226,18 @@ vips__webp_read_file_header( const char *filename, VipsImage *out )
|
||||
int
|
||||
vips__webp_read_file( const char *filename, VipsImage *out )
|
||||
{
|
||||
printf( "vips__webp_read_file\n" );
|
||||
Read *read;
|
||||
|
||||
if( !(read = read_new( filename, NULL, 0 )) ) {
|
||||
vips_error( "webp2vips",
|
||||
_( "unable to open \"%s\"" ), filename );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( read_image( read, out ) )
|
||||
return( -1 );
|
||||
|
||||
read_free( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -80,7 +245,18 @@ vips__webp_read_file( const char *filename, VipsImage *out )
|
||||
int
|
||||
vips__webp_read_buffer_header( void *buf, size_t len, VipsImage *out )
|
||||
{
|
||||
printf( "vips__webp_read_buffer_header\n" );
|
||||
Read *read;
|
||||
|
||||
if( !(read = read_new( NULL, buf, len )) ) {
|
||||
vips_error( "webp2vips",
|
||||
"%s", _( "unable to open buffer" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( read_header( read, out ) )
|
||||
return( -1 );
|
||||
|
||||
read_free( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -88,11 +264,18 @@ vips__webp_read_buffer_header( void *buf, size_t len, VipsImage *out )
|
||||
int
|
||||
vips__webp_read_buffer( void *buf, size_t len, VipsImage *out )
|
||||
{
|
||||
printf( "vips__webp_read_buffer\n" );
|
||||
Read *read;
|
||||
|
||||
if( !(read = read_new( NULL, buf, len )) ) {
|
||||
vips_error( "webp2vips",
|
||||
"%s", _( "unable to open buffer" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( read_image( read, out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /*HAVE_LIBWEBP*/
|
||||
|
||||
|
||||
|
@ -37,9 +37,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
#define VIPS_DEBUG
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
|
Loading…
Reference in New Issue
Block a user