works!
This commit is contained in:
parent
efe824ec13
commit
d4b4eb44a3
@ -5,6 +5,7 @@
|
|||||||
- revise header get/set functions
|
- revise header get/set functions
|
||||||
- better vipsheader behaviour with complex field types
|
- better vipsheader behaviour with complex field types
|
||||||
- added vips_image_hasalpha()
|
- added vips_image_hasalpha()
|
||||||
|
- added vips_thumbnail() / vips_thumbnail_buffer()
|
||||||
|
|
||||||
18/10/16 started 8.4.3
|
18/10/16 started 8.4.3
|
||||||
- fix error detection in gif_close, thanks aaron42net
|
- fix error detection in gif_close, thanks aaron42net
|
||||||
|
8
TODO
8
TODO
@ -1,3 +1,11 @@
|
|||||||
|
- add thumbnail tests
|
||||||
|
|
||||||
|
rework vipsthumbnail.c
|
||||||
|
|
||||||
|
benchmark
|
||||||
|
|
||||||
|
docs
|
||||||
|
|
||||||
- not sure about utf8 error messages on win
|
- not sure about utf8 error messages on win
|
||||||
|
|
||||||
- strange:
|
- strange:
|
||||||
|
@ -214,6 +214,7 @@ vips_foreign_load_png_buffer_class_init( VipsForeignLoadPngBufferClass *class )
|
|||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignLoadPngBuffer, buf ),
|
G_STRUCT_OFFSET( VipsForeignLoadPngBuffer, buf ),
|
||||||
VIPS_TYPE_BLOB );
|
VIPS_TYPE_BLOB );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -63,6 +63,11 @@ int vips_reduceh( VipsImage *in, VipsImage **out, double hshrink, ... )
|
|||||||
int vips_reducev( VipsImage *in, VipsImage **out, double vshrink, ... )
|
int vips_reducev( VipsImage *in, VipsImage **out, double vshrink, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
|
||||||
|
int vips_thumbnail( const char *filename, VipsImage **out, int width, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_thumbnail_buffer( void *buf, size_t len, VipsImage **out, int width, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
int vips_similarity( VipsImage *in, VipsImage **out, ... )
|
int vips_similarity( VipsImage *in, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_affine( VipsImage *in, VipsImage **out,
|
int vips_affine( VipsImage *in, VipsImage **out,
|
||||||
|
@ -133,7 +133,8 @@ vips_resample_init( VipsResample *resample )
|
|||||||
void
|
void
|
||||||
vips_resample_operation_init( void )
|
vips_resample_operation_init( void )
|
||||||
{
|
{
|
||||||
extern GType vips_thumbnail_get_type( void );
|
extern GType vips_thumbnail_file_get_type( void );
|
||||||
|
extern GType vips_thumbnail_buffer_get_type( void );
|
||||||
extern GType vips_mapim_get_type( void );
|
extern GType vips_mapim_get_type( void );
|
||||||
extern GType vips_shrink_get_type( void );
|
extern GType vips_shrink_get_type( void );
|
||||||
extern GType vips_shrinkh_get_type( void );
|
extern GType vips_shrinkh_get_type( void );
|
||||||
@ -146,7 +147,8 @@ vips_resample_operation_init( void )
|
|||||||
extern GType vips_similarity_get_type( void );
|
extern GType vips_similarity_get_type( void );
|
||||||
extern GType vips_resize_get_type( void );
|
extern GType vips_resize_get_type( void );
|
||||||
|
|
||||||
vips_thumbnail_get_type();
|
vips_thumbnail_file_get_type();
|
||||||
|
vips_thumbnail_buffer_get_type();
|
||||||
vips_mapim_get_type();
|
vips_mapim_get_type();
|
||||||
vips_shrink_get_type();
|
vips_shrink_get_type();
|
||||||
vips_shrinkh_get_type();
|
vips_shrinkh_get_type();
|
||||||
|
@ -198,27 +198,27 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
vips_info( "thumbnail", "selected loader is %s",
|
vips_info( "thumbnail", "selected loader is %s",
|
||||||
thumbnail->loader );
|
thumbnail->loader );
|
||||||
vips_info( "thumbnail", "input size is %d x %d",
|
vips_info( "thumbnail", "input size is %d x %d",
|
||||||
thumbnail->width, thumbnail->height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
|
|
||||||
shrink = 1;
|
shrink = 1;
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) {
|
if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) {
|
||||||
shrink = vips_thumbnail_find_jpegshrink( thumbnail,
|
shrink = vips_thumbnail_find_jpegshrink( thumbnail,
|
||||||
thumbnail->width, thumbnail->height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
vips_info( "thumbnail",
|
vips_info( "thumbnail",
|
||||||
"loading jpeg with factor %d pre-shrink", shrink );
|
"loading jpeg with factor %d pre-shrink", shrink );
|
||||||
}
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) ||
|
else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) ||
|
||||||
vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) {
|
vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) {
|
||||||
scale = 1.0 / vips_thumbnail_calculate_shrink( thumbnail,
|
scale = 1.0 / vips_thumbnail_calculate_shrink( thumbnail,
|
||||||
thumbnail->width, thumbnail->height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
vips_info( "thumbnail",
|
vips_info( "thumbnail",
|
||||||
"loading PDF/SVG with factor %g pre-scale", scale );
|
"loading PDF/SVG with factor %g pre-scale", scale );
|
||||||
}
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) {
|
else if( vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) {
|
||||||
shrink = vips_thumbnail_calculate_shrink( thumbnail,
|
shrink = vips_thumbnail_calculate_shrink( thumbnail,
|
||||||
thumbnail->width, thumbnail->height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
vips_info( "thumbnail",
|
vips_info( "thumbnail",
|
||||||
"loading webp with factor %d pre-shrink", shrink );
|
"loading webp with factor %d pre-shrink", shrink );
|
||||||
}
|
}
|
||||||
@ -259,6 +259,9 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_thumbnail_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_thumbnail_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
if( !vips_object_argument_isset( object, "height" ) )
|
||||||
|
thumbnail->height = thumbnail->width;
|
||||||
|
|
||||||
if( !(t[0] = vips_thumbnail_open( thumbnail )) )
|
if( !(t[0] = vips_thumbnail_open( thumbnail )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[0];
|
in = t[0];
|
||||||
@ -496,14 +499,14 @@ vips_thumbnail_class_init( VipsThumbnailClass *class )
|
|||||||
_( "Size to this width" ),
|
_( "Size to this width" ),
|
||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsThumbnail, width ),
|
G_STRUCT_OFFSET( VipsThumbnail, width ),
|
||||||
1, VIPS_MAX_COORD, 0 );
|
1, VIPS_MAX_COORD, 1 );
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "height", 113,
|
VIPS_ARG_INT( class, "height", 113,
|
||||||
_( "Target height" ),
|
_( "Target height" ),
|
||||||
_( "Size to this height" ),
|
_( "Size to this height" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsThumbnail, height ),
|
G_STRUCT_OFFSET( VipsThumbnail, height ),
|
||||||
1, VIPS_MAX_COORD, 0 );
|
1, VIPS_MAX_COORD, 1 );
|
||||||
|
|
||||||
VIPS_ARG_BOOL( class, "auto_rotate", 114,
|
VIPS_ARG_BOOL( class, "auto_rotate", 114,
|
||||||
_( "Auto rotate" ),
|
_( "Auto rotate" ),
|
||||||
@ -545,6 +548,8 @@ vips_thumbnail_class_init( VipsThumbnailClass *class )
|
|||||||
static void
|
static void
|
||||||
vips_thumbnail_init( VipsThumbnail *thumbnail )
|
vips_thumbnail_init( VipsThumbnail *thumbnail )
|
||||||
{
|
{
|
||||||
|
thumbnail->width = 1;
|
||||||
|
thumbnail->height = 1;
|
||||||
thumbnail->auto_rotate = TRUE;
|
thumbnail->auto_rotate = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,8 +588,8 @@ vips_thumbnail_file_get_info( VipsThumbnail *thumbnail )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open an image, pre-shrinking as appropriate. Someformats use shrink, some
|
/* Open an image, pre-shrinking as appropriate. Some formats use shrink, some
|
||||||
* scale, it's OK to pass extra ones.
|
* scale, never both.
|
||||||
*/
|
*/
|
||||||
static VipsImage *
|
static VipsImage *
|
||||||
vips_thumbnail_file_open( VipsThumbnail *thumbnail, int shrink, double scale )
|
vips_thumbnail_file_open( VipsThumbnail *thumbnail, int shrink, double scale )
|
||||||
@ -593,11 +598,20 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, int shrink, double scale )
|
|||||||
|
|
||||||
/* We can't use UNBUFERRED safely on very-many-core systems.
|
/* We can't use UNBUFERRED safely on very-many-core systems.
|
||||||
*/
|
*/
|
||||||
return( vips_image_new_from_file( file->filename,
|
if( shrink != 1 )
|
||||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
return( vips_image_new_from_file( file->filename,
|
||||||
"shrink", shrink,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
"scale", scale,
|
"shrink", shrink,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
|
else if( scale != 1.0 )
|
||||||
|
return( vips_image_new_from_file( file->filename,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"scale", scale,
|
||||||
|
NULL ) );
|
||||||
|
else
|
||||||
|
return( vips_image_new_from_file( file->filename,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -665,4 +679,142 @@ vips_thumbnail( const char *filename, VipsImage **out, int width, ... )
|
|||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsThumbnailBuffer {
|
||||||
|
VipsThumbnail parent_object;
|
||||||
|
|
||||||
|
VipsArea *buf;
|
||||||
|
} VipsThumbnailBuffer;
|
||||||
|
|
||||||
|
typedef VipsThumbnailClass VipsThumbnailBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsThumbnailBuffer, vips_thumbnail_buffer,
|
||||||
|
vips_thumbnail_get_type() );
|
||||||
|
|
||||||
|
/* Get the info from a buffer.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vips_thumbnail_buffer_get_info( VipsThumbnail *thumbnail )
|
||||||
|
{
|
||||||
|
VipsThumbnailBuffer *buffer = (VipsThumbnailBuffer *) thumbnail;
|
||||||
|
|
||||||
|
VipsImage *image;
|
||||||
|
|
||||||
|
vips_info( "thumbnail", "thumbnailing %zd bytes of data",
|
||||||
|
buffer->buf->length );
|
||||||
|
|
||||||
|
if( !(thumbnail->loader = vips_foreign_find_load_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length )) ||
|
||||||
|
!(image = vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length, "", NULL )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
thumbnail->input_width = image->Xsize;
|
||||||
|
thumbnail->input_height = image->Ysize;
|
||||||
|
thumbnail->angle = vips_autorot_get_angle( image );
|
||||||
|
|
||||||
|
g_object_unref( image );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open an image, pre-shrinking as appropriate. Some formats use shrink, some
|
||||||
|
* scale, never both.
|
||||||
|
*/
|
||||||
|
static VipsImage *
|
||||||
|
vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, int shrink, double scale )
|
||||||
|
{
|
||||||
|
VipsThumbnailBuffer *buffer = (VipsThumbnailBuffer *) thumbnail;
|
||||||
|
|
||||||
|
/* We can't use UNBUFERRED safely on very-many-core systems.
|
||||||
|
*/
|
||||||
|
if( shrink != 1 )
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length, "",
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"shrink", shrink,
|
||||||
|
NULL ) );
|
||||||
|
else if( scale != 1.0 )
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length, "",
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"scale", scale,
|
||||||
|
NULL ) );
|
||||||
|
else
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length, "",
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_thumbnail_buffer_class_init( VipsThumbnailClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||||
|
VipsThumbnailClass *thumbnail_class = VIPS_THUMBNAIL_CLASS( class );
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
vobject_class->nickname = "thumbnail_buffer";
|
||||||
|
vobject_class->description = _( "generate thumbnail from buffer" );
|
||||||
|
|
||||||
|
thumbnail_class->get_info = vips_thumbnail_buffer_get_info;
|
||||||
|
thumbnail_class->open = vips_thumbnail_buffer_open;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to load from" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsThumbnailBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_thumbnail_buffer_init( VipsThumbnailBuffer *buffer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_thumbnail_buffer:
|
||||||
|
* @buf: memory area to load
|
||||||
|
* @len: size of memory area
|
||||||
|
* @out: output image
|
||||||
|
* @width: target width in pixels
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
* Optional arguments:
|
||||||
|
*
|
||||||
|
* * @height: %gint, target height in pixels
|
||||||
|
* * @auto_rotate: %gboolean, rotate upright using orientation tag
|
||||||
|
* * @crop: %gboolean, shrink and crop to fill target
|
||||||
|
* * @linear: %gboolean, perform shrink in linear light
|
||||||
|
* * @import_probuffer: %gchararray, fallback import ICC probuffer
|
||||||
|
* * @export_probuffer: %gchararray, export ICC probuffer
|
||||||
|
*
|
||||||
|
* Exacty as vips_thumbnail(), but read from a memory buffer.
|
||||||
|
*
|
||||||
|
* See also: vips_thumbnail().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_thumbnail_buffer( void *buf, size_t len, VipsImage **out, int width, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
VipsBlob *blob;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* We don't take a copy of the data or free it.
|
||||||
|
*/
|
||||||
|
blob = vips_blob_new( NULL, buf, len );
|
||||||
|
|
||||||
|
va_start( ap, width );
|
||||||
|
result = vips_call_split( "thumbnail_buffer", ap, blob, out, width );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user