Merge branch '8.9'
This commit is contained in:
commit
46da95f30f
@ -7,6 +7,10 @@
|
|||||||
- libtiff LOGLUV images load and save as libvips XYZ
|
- libtiff LOGLUV images load and save as libvips XYZ
|
||||||
- add gifload_source
|
- add gifload_source
|
||||||
|
|
||||||
|
31/1/19 started 8.9.2
|
||||||
|
- fix a deadlock with --vips-leak [DarthSim]
|
||||||
|
- better gifload behaviour for DISPOSAL_UNSPECIFIED [DarthSim]
|
||||||
|
|
||||||
20/6/19 started 8.9.1
|
20/6/19 started 8.9.1
|
||||||
- don't use the new source loaders for new_from_file or new_from_buffer, it
|
- don't use the new source loaders for new_from_file or new_from_buffer, it
|
||||||
will break the loader priority system
|
will break the loader priority system
|
||||||
|
@ -37,6 +37,9 @@
|
|||||||
* 30/1/19
|
* 30/1/19
|
||||||
* - rework on top of VipsSource
|
* - rework on top of VipsSource
|
||||||
* - add gifload_source
|
* - add gifload_source
|
||||||
|
* 31/1/20
|
||||||
|
* - treat DISPOSAL_UNSPECIFIED as _DO_NOT, since that's what many GIFs
|
||||||
|
* in the wild appear to do
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -847,8 +850,12 @@ vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
|||||||
/* In DISPOSE_DO_NOT mode, the previous frame shows
|
/* In DISPOSE_DO_NOT mode, the previous frame shows
|
||||||
* through (ie. we do nothing). In all other modes,
|
* through (ie. we do nothing). In all other modes,
|
||||||
* it's just transparent.
|
* it's just transparent.
|
||||||
|
*
|
||||||
|
* Many GIFs use DISPOSAL_UNSPECIFIED to mean DO_NOT,
|
||||||
|
* so use that for previous frame as well.
|
||||||
*/
|
*/
|
||||||
if( gif->dispose != DISPOSE_DO_NOT )
|
if( gif->dispose != DISPOSE_DO_NOT &&
|
||||||
|
gif->dispose != DISPOSAL_UNSPECIFIED )
|
||||||
iq[x] = 0;
|
iq[x] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -971,6 +978,20 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef VIPS_DEBUG
|
||||||
|
static const char *
|
||||||
|
dispose2str( int dispose )
|
||||||
|
{
|
||||||
|
switch( dispose ) {
|
||||||
|
case DISPOSAL_UNSPECIFIED: return( "DISPOSAL_UNSPECIFIED" );
|
||||||
|
case DISPOSE_DO_NOT: return( "DISPOSE_DO_NOT" );
|
||||||
|
case DISPOSE_BACKGROUND: return( "DISPOSE_BACKGROUND" );
|
||||||
|
case DISPOSE_PREVIOUS: return( "DISPOSE_PREVIOUS" );
|
||||||
|
default: return( "<unknown>" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /*VIPS_DEBUG*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_gif_extension( VipsForeignLoadGif *gif )
|
vips_foreign_load_gif_extension( VipsForeignLoadGif *gif )
|
||||||
{
|
{
|
||||||
@ -993,15 +1014,18 @@ vips_foreign_load_gif_extension( VipsForeignLoadGif *gif )
|
|||||||
* is being set.
|
* is being set.
|
||||||
*/
|
*/
|
||||||
gif->transparency = -1;
|
gif->transparency = -1;
|
||||||
if( extension[1] & 0x1 )
|
if( extension[1] & 0x1 ) {
|
||||||
gif->transparency = extension[4];
|
gif->transparency = extension[4];
|
||||||
|
VIPS_DEBUG_MSG( "vips_foreign_load_gif_extension: "
|
||||||
|
"transparency = %d\n", gif->transparency );
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the current dispose mode. This is read during frame load
|
/* Set the current dispose mode. This is read during frame load
|
||||||
* to set the meaning of background and transparent pixels.
|
* to set the meaning of background and transparent pixels.
|
||||||
*/
|
*/
|
||||||
gif->dispose = (extension[1] >> 2) & 0x7;
|
gif->dispose = (extension[1] >> 2) & 0x7;
|
||||||
VIPS_DEBUG_MSG( "vips_foreign_load_gif_extension: "
|
VIPS_DEBUG_MSG( "vips_foreign_load_gif_extension: "
|
||||||
"dispose = %d\n", gif->dispose );
|
"dispose = %s\n", dispose2str( gif->dispose ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
while( extension != NULL )
|
while( extension != NULL )
|
||||||
|
@ -192,6 +192,8 @@ int vips__view_image( struct _VipsImage *image );
|
|||||||
*/
|
*/
|
||||||
extern int _vips__argument_id;
|
extern int _vips__argument_id;
|
||||||
|
|
||||||
|
void vips__meta_init( void );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
* - add vips_image_get_n_pages()
|
* - add vips_image_get_n_pages()
|
||||||
* 20/6/19
|
* 20/6/19
|
||||||
* - add vips_image_get/set_array_int()
|
* - add vips_image_get/set_array_int()
|
||||||
|
* 31/1/19
|
||||||
|
* - lock for metadata changes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -130,6 +132,11 @@
|
|||||||
* these types, it can be copied between images efficiently.
|
* these types, it can be copied between images efficiently.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Use in various small places where we need a mutex and it's not worth
|
||||||
|
* making a private one.
|
||||||
|
*/
|
||||||
|
static GMutex *vips__meta_lock = NULL;
|
||||||
|
|
||||||
/* We have to keep the gtype as a string, since we statically init this.
|
/* We have to keep the gtype as a string, since we statically init this.
|
||||||
*/
|
*/
|
||||||
typedef struct _HeaderField {
|
typedef struct _HeaderField {
|
||||||
@ -934,10 +941,10 @@ meta_cp( VipsImage *dst, const VipsImage *src )
|
|||||||
/* We lock with vips_image_set() to stop races in highly-
|
/* We lock with vips_image_set() to stop races in highly-
|
||||||
* threaded applications.
|
* threaded applications.
|
||||||
*/
|
*/
|
||||||
g_mutex_lock( vips__global_lock );
|
g_mutex_lock( vips__meta_lock );
|
||||||
vips_slist_map2( src->meta_traverse,
|
vips_slist_map2( src->meta_traverse,
|
||||||
(VipsSListMap2Fn) meta_cp_field, dst, NULL );
|
(VipsSListMap2Fn) meta_cp_field, dst, NULL );
|
||||||
g_mutex_unlock( vips__global_lock );
|
g_mutex_unlock( vips__meta_lock );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -1025,13 +1032,6 @@ vips_image_set( VipsImage *image, const char *name, GValue *value )
|
|||||||
g_assert( name );
|
g_assert( name );
|
||||||
g_assert( value );
|
g_assert( value );
|
||||||
|
|
||||||
/* If this image is shared, block metadata changes.
|
|
||||||
*/
|
|
||||||
if( G_OBJECT( image )->ref_count > 1 ) {
|
|
||||||
g_warning( "can't set metadata \"%s\" on shared image", name );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_init( image );
|
meta_init( image );
|
||||||
|
|
||||||
/* We lock between modifying metadata and copying metadata between
|
/* We lock between modifying metadata and copying metadata between
|
||||||
@ -1041,9 +1041,9 @@ vips_image_set( VipsImage *image, const char *name, GValue *value )
|
|||||||
* metadata copy on another -- this can lead to crashes in
|
* metadata copy on another -- this can lead to crashes in
|
||||||
* highly-threaded applications.
|
* highly-threaded applications.
|
||||||
*/
|
*/
|
||||||
g_mutex_lock( vips__global_lock );
|
g_mutex_lock( vips__meta_lock );
|
||||||
(void) meta_new( image, name, value );
|
(void) meta_new( image, name, value );
|
||||||
g_mutex_unlock( vips__global_lock );
|
g_mutex_unlock( vips__meta_lock );
|
||||||
|
|
||||||
/* If we're setting an EXIF data block, we need to automatically expand
|
/* If we're setting an EXIF data block, we need to automatically expand
|
||||||
* out all the tags. This will set things like xres/yres too.
|
* out all the tags. This will set things like xres/yres too.
|
||||||
@ -1240,14 +1240,6 @@ vips_image_remove( VipsImage *image, const char *name )
|
|||||||
|
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
|
|
||||||
/* If this image is shared, block metadata changes.
|
|
||||||
*/
|
|
||||||
if( G_OBJECT( image )->ref_count > 1 ) {
|
|
||||||
g_warning( "can't remove metadata \"%s\" on shared image",
|
|
||||||
name );
|
|
||||||
return( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( image->meta ) {
|
if( image->meta ) {
|
||||||
/* We lock between modifying metadata and copying metadata
|
/* We lock between modifying metadata and copying metadata
|
||||||
* between images, see meta_cp().
|
* between images, see meta_cp().
|
||||||
@ -1256,9 +1248,9 @@ vips_image_remove( VipsImage *image, const char *name )
|
|||||||
* racing with metadata copy on another -- this can lead to
|
* racing with metadata copy on another -- this can lead to
|
||||||
* crashes in highly-threaded applications.
|
* crashes in highly-threaded applications.
|
||||||
*/
|
*/
|
||||||
g_mutex_lock( vips__global_lock );
|
g_mutex_lock( vips__meta_lock );
|
||||||
result = g_hash_table_remove( image->meta, name );
|
result = g_hash_table_remove( image->meta, name );
|
||||||
g_mutex_unlock( vips__global_lock );
|
g_mutex_unlock( vips__meta_lock );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
@ -2027,3 +2019,12 @@ vips_image_get_history( VipsImage *image )
|
|||||||
|
|
||||||
return( image->Hist ? image->Hist : "" );
|
return( image->Hist ? image->Hist : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called during vips_init().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vips__meta_init( void )
|
||||||
|
{
|
||||||
|
if( !vips__meta_lock )
|
||||||
|
vips__meta_lock = vips_g_mutex_new();
|
||||||
|
}
|
||||||
|
@ -382,6 +382,7 @@ vips_init( const char *argv0 )
|
|||||||
|
|
||||||
vips__threadpool_init();
|
vips__threadpool_init();
|
||||||
vips__buffer_init();
|
vips__buffer_init();
|
||||||
|
vips__meta_init();
|
||||||
|
|
||||||
/* This does an unsynchronised static hash table init on first call --
|
/* This does an unsynchronised static hash table init on first call --
|
||||||
* we have to make sure we do this single-threaded. See:
|
* we have to make sure we do this single-threaded. See:
|
||||||
|
Loading…
Reference in New Issue
Block a user