start revising heifload
not quite working
This commit is contained in:
parent
175408733f
commit
7ea34382a3
@ -152,37 +152,42 @@ typedef struct _VipsForeignLoadHeif {
|
||||
int stride;
|
||||
const uint8_t *data;
|
||||
|
||||
/* Set from subclasses.
|
||||
*/
|
||||
VipsSource *source;
|
||||
|
||||
/* The reader struct. We use this to attach to our VipsSource. This
|
||||
* has to be alloced rather than in our struct, since it may change
|
||||
* size in libheif API versions.
|
||||
*/
|
||||
struct heif_reader *reader;
|
||||
|
||||
/* When we see EOF from read(), record the source length here.
|
||||
*/
|
||||
gint64 length;
|
||||
|
||||
} VipsForeignLoadHeif;
|
||||
|
||||
typedef struct _VipsForeignLoadHeifClass {
|
||||
VipsForeignLoadClass parent_class;
|
||||
|
||||
/* Open the reader, eg. call heif_context_read_from_memory() etc. This
|
||||
* has to be a vfunc so generate can restart after minimise.
|
||||
*/
|
||||
int (*open)( VipsForeignLoadHeif *heif );
|
||||
|
||||
} VipsForeignLoadHeifClass;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadHeif, vips_foreign_load_heif,
|
||||
VIPS_TYPE_FOREIGN_LOAD );
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_close( VipsForeignLoadHeif *heif )
|
||||
{
|
||||
VIPS_FREEF( heif_image_release, heif->img );
|
||||
heif->data = NULL;
|
||||
VIPS_FREEF( heif_image_handle_release, heif->handle );
|
||||
VIPS_FREEF( heif_context_free, heif->ctx );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_dispose( GObject *gobject )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) gobject;
|
||||
|
||||
vips_foreign_load_heif_close( heif );
|
||||
heif->data = NULL;
|
||||
VIPS_FREEF( heif_image_release, heif->img );
|
||||
VIPS_FREEF( heif_image_handle_release, heif->handle );
|
||||
VIPS_FREEF( heif_context_free, heif->ctx );
|
||||
VIPS_FREE( heif->id );
|
||||
VIPS_FREE( heif->reader );
|
||||
VIPS_UNREF( heif->source );
|
||||
|
||||
G_OBJECT_CLASS( vips_foreign_load_heif_parent_class )->
|
||||
dispose( gobject );
|
||||
@ -196,6 +201,31 @@ vips__heif_error( struct heif_error *error )
|
||||
error->subcode );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) object;
|
||||
|
||||
if( !heif->ctx ) {
|
||||
struct heif_error error;
|
||||
|
||||
heif->ctx = heif_context_alloc();
|
||||
error = heif_context_read_from_reader( heif->ctx,
|
||||
heif->reader, heif, NULL );
|
||||
if( error.code ) {
|
||||
vips__heif_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
static const char *heif_magic[] = {
|
||||
"ftypheic", /* A regular heif image */
|
||||
"ftypheix", /* Extended range (>8 bit) image */
|
||||
@ -308,6 +338,8 @@ vips_foreign_load_heif_set_page( VipsForeignLoadHeif *heif,
|
||||
static int
|
||||
vips_foreign_load_heif_set_header( VipsForeignLoadHeif *heif, VipsImage *out )
|
||||
{
|
||||
VipsForeignLoad *load = (VipsForeignLoad *) heif;
|
||||
|
||||
int bands;
|
||||
int i;
|
||||
/* Surely, 16 metadata items will be enough for anyone.
|
||||
@ -464,6 +496,9 @@ vips_foreign_load_heif_set_header( VipsForeignLoadHeif *heif, VipsImage *out )
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB,
|
||||
1.0, 1.0 );
|
||||
|
||||
VIPS_SETSTR( load->out->filename,
|
||||
vips_connection_filename( VIPS_CONNECTION( heif->source ) ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
@ -506,16 +541,11 @@ vips_foreign_load_heif_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) load;
|
||||
VipsForeignLoadHeifClass *heif_class =
|
||||
VIPS_FOREIGN_LOAD_HEIF_GET_CLASS( heif );
|
||||
|
||||
struct heif_error error;
|
||||
heif_item_id primary_id;
|
||||
int i;
|
||||
|
||||
if( heif_class->open( heif ) )
|
||||
return( -1 );
|
||||
|
||||
heif->n_top = heif_context_get_number_of_top_level_images( heif->ctx );
|
||||
heif->id = VIPS_ARRAY( NULL, heif->n_top, heif_item_id );
|
||||
heif_context_get_list_of_top_level_image_IDs( heif->ctx,
|
||||
@ -645,7 +675,7 @@ vips_foreign_load_heif_header( VipsForeignLoad *load )
|
||||
if( vips_foreign_load_heif_set_header( heif, load->out ) )
|
||||
return( -1 );
|
||||
|
||||
vips_foreign_load_heif_close( heif );
|
||||
vips_source_minimise( heif->source );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -656,8 +686,6 @@ vips_foreign_load_heif_generate( VipsRegion *or,
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) a;
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( heif );
|
||||
VipsForeignLoadHeifClass *heif_class =
|
||||
VIPS_FOREIGN_LOAD_HEIF_GET_CLASS( heif );
|
||||
VipsRect *r = &or->valid;
|
||||
|
||||
int page = r->top / heif->page_height + heif->page;
|
||||
@ -669,9 +697,6 @@ vips_foreign_load_heif_generate( VipsRegion *or,
|
||||
|
||||
g_assert( r->height == 1 );
|
||||
|
||||
if( heif_class->open( heif ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_foreign_load_heif_set_page( heif, page, heif->thumbnail ) )
|
||||
return( -1 );
|
||||
|
||||
@ -779,15 +804,13 @@ vips_foreign_load_heif_generate( VipsRegion *or,
|
||||
static void
|
||||
vips_foreign_load_heif_minimise( VipsObject *object, VipsForeignLoadHeif *heif )
|
||||
{
|
||||
vips_foreign_load_heif_close( heif );
|
||||
vips_source_minimise( heif->source );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_load( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) load;
|
||||
VipsForeignLoadHeifClass *class =
|
||||
VIPS_FOREIGN_LOAD_HEIF_GET_CLASS( heif );
|
||||
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( load ), 3 );
|
||||
@ -796,9 +819,6 @@ vips_foreign_load_heif_load( VipsForeignLoad *load )
|
||||
printf( "vips_foreign_load_heif_load: loading image\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( class->open( heif ) )
|
||||
return( -1 );
|
||||
|
||||
t[0] = vips_image_new();
|
||||
if( vips_foreign_load_heif_set_header( heif, t[0] ) )
|
||||
return( -1 );
|
||||
@ -817,20 +837,12 @@ vips_foreign_load_heif_load( VipsForeignLoad *load )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_open( VipsForeignLoadHeif *heif )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_class_init( VipsForeignLoadHeifClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
VipsForeignLoadHeifClass *heif_class =
|
||||
(VipsForeignLoadHeifClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_heif_dispose;
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
@ -838,13 +850,12 @@ vips_foreign_load_heif_class_init( VipsForeignLoadHeifClass *class )
|
||||
|
||||
object_class->nickname = "heifload_base";
|
||||
object_class->description = _( "load a HEIF image" );
|
||||
object_class->build = vips_foreign_load_heif_build;
|
||||
|
||||
load_class->get_flags = vips_foreign_load_heif_get_flags;
|
||||
load_class->header = vips_foreign_load_heif_header;
|
||||
load_class->load = vips_foreign_load_heif_load;
|
||||
|
||||
heif_class->open = vips_foreign_load_heif_open;
|
||||
|
||||
VIPS_ARG_INT( class, "page", 2,
|
||||
_( "Page" ),
|
||||
_( "Load this page from the file" ),
|
||||
@ -875,10 +886,77 @@ vips_foreign_load_heif_class_init( VipsForeignLoadHeifClass *class )
|
||||
|
||||
}
|
||||
|
||||
static gint64
|
||||
vips_foreign_load_heif_get_position( void *userdata )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) userdata;
|
||||
|
||||
return( vips_source_seek( heif->source, 0L, SEEK_CUR ) );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_read( void *data, size_t size, void *userdata )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) userdata;
|
||||
|
||||
int result;
|
||||
|
||||
result = vips_source_read( heif->source, data, size );
|
||||
if( result == 0 ) {
|
||||
printf( "vips_foreign_load_heif_read: seen EOF\n" );
|
||||
heif->length = vips_source_seek( heif->source, 0L, SEEK_CUR );
|
||||
}
|
||||
if( result < 0 )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_seek( gint64 position, void *userdata )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) userdata;
|
||||
|
||||
vips_source_seek( heif->source, position, SEEK_SET );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static enum heif_reader_grow_status
|
||||
vips_foreign_load_heif_wait_for_file_size( gint64 target_size, void *userdata )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) userdata;
|
||||
|
||||
return( heif_reader_grow_status_size_reached );
|
||||
|
||||
if( heif->length == -1 ||
|
||||
target_size < heif->length )
|
||||
/* We've not seen EOF yet (so seeking to any point is fine), OR
|
||||
* we've seen EOF, and this target is less than that.
|
||||
*/
|
||||
return( heif_reader_grow_status_size_reached );
|
||||
else
|
||||
/* We've seen EOF, we know the length, and this is too far.
|
||||
*/
|
||||
return( heif_reader_grow_status_size_beyond_eof );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_init( VipsForeignLoadHeif *heif )
|
||||
{
|
||||
heif->n = 1;
|
||||
heif->length = -1;
|
||||
|
||||
heif->reader = VIPS_ARRAY( NULL, 1, struct heif_reader );
|
||||
|
||||
/* The first version to support heif_reader.
|
||||
*/
|
||||
heif->reader->reader_api_version = 1.3;
|
||||
heif->reader->get_position = vips_foreign_load_heif_get_position;
|
||||
heif->reader->read = vips_foreign_load_heif_read;
|
||||
heif->reader->seek = vips_foreign_load_heif_seek;
|
||||
heif->reader->wait_for_file_size =
|
||||
vips_foreign_load_heif_wait_for_file_size;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadHeifFile {
|
||||
@ -895,6 +973,24 @@ typedef VipsForeignLoadHeifClass VipsForeignLoadHeifFileClass;
|
||||
G_DEFINE_TYPE( VipsForeignLoadHeifFile, vips_foreign_load_heif_file,
|
||||
vips_foreign_load_heif_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_file_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadHeifFile *file = (VipsForeignLoadHeifFile *) object;
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) object;
|
||||
|
||||
if( file->filename )
|
||||
if( !(heif->source =
|
||||
vips_source_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_file_is_a( const char *filename )
|
||||
{
|
||||
@ -906,25 +1002,6 @@ vips_foreign_load_heif_file_is_a( const char *filename )
|
||||
return( vips_foreign_load_heif_is_a( buf, 12 ) );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_file_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) load;
|
||||
VipsForeignLoadHeifFile *file = (VipsForeignLoadHeifFile *) load;
|
||||
|
||||
if( VIPS_FOREIGN_LOAD_CLASS(
|
||||
vips_foreign_load_heif_file_parent_class )->header( load ) ) {
|
||||
/* Close early if our base class fails to read.
|
||||
*/
|
||||
vips_foreign_load_heif_close( heif );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
VIPS_SETSTR( load->out->filename, file->filename );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
const char *vips__heif_suffs[] = {
|
||||
".heic",
|
||||
".heif",
|
||||
@ -932,31 +1009,6 @@ const char *vips__heif_suffs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_file_open( VipsForeignLoadHeif *heif )
|
||||
{
|
||||
VipsForeignLoadHeifFile *file = (VipsForeignLoadHeifFile *) heif;
|
||||
|
||||
if( !heif->ctx ) {
|
||||
struct heif_error error;
|
||||
|
||||
heif->ctx = heif_context_alloc();
|
||||
|
||||
error = heif_context_read_from_file( heif->ctx,
|
||||
file->filename, NULL );
|
||||
if( error.code ) {
|
||||
/* Make we close the fd as soon as we can on error.
|
||||
*/
|
||||
vips_foreign_load_heif_close( heif );
|
||||
vips__heif_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
return( VIPS_FOREIGN_LOAD_HEIF_CLASS(
|
||||
vips_foreign_load_heif_file_parent_class )->open( heif ) );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_file_class_init( VipsForeignLoadHeifFileClass *class )
|
||||
{
|
||||
@ -964,20 +1016,16 @@ vips_foreign_load_heif_file_class_init( VipsForeignLoadHeifFileClass *class )
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
VipsForeignLoadHeifClass *heif_class =
|
||||
(VipsForeignLoadHeifClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "heifload";
|
||||
object_class->build = vips_foreign_load_heif_file_build;
|
||||
|
||||
foreign_class->suffs = vips__heif_suffs;
|
||||
|
||||
load_class->is_a = vips_foreign_load_heif_file_is_a;
|
||||
load_class->header = vips_foreign_load_heif_file_header;
|
||||
|
||||
heif_class->open = vips_foreign_load_heif_file_open;
|
||||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
@ -1007,35 +1055,32 @@ typedef VipsForeignLoadHeifClass VipsForeignLoadHeifBufferClass;
|
||||
G_DEFINE_TYPE( VipsForeignLoadHeifBuffer, vips_foreign_load_heif_buffer,
|
||||
vips_foreign_load_heif_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_buffer_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadHeifBuffer *buffer =
|
||||
(VipsForeignLoadHeifBuffer *) object;
|
||||
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) object;
|
||||
|
||||
if( buffer->buf )
|
||||
if( !(heif->source = vips_source_new_from_memory(
|
||||
VIPS_AREA( buffer->buf )->data,
|
||||
VIPS_AREA( buffer->buf )->length )) )
|
||||
return( -1 );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_heif_buffer_is_a( const void *buf, size_t len )
|
||||
{
|
||||
return( vips_foreign_load_heif_is_a( buf, len ) );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_heif_buffer_open( VipsForeignLoadHeif *heif )
|
||||
{
|
||||
VipsForeignLoadHeifBuffer *buffer = (VipsForeignLoadHeifBuffer *) heif;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_heif_buffer_open:\n" );
|
||||
|
||||
if( !heif->ctx ) {
|
||||
struct heif_error error;
|
||||
|
||||
heif->ctx = heif_context_alloc();
|
||||
error = heif_context_read_from_memory( heif->ctx,
|
||||
buffer->buf->data, buffer->buf->length, NULL );
|
||||
if( error.code ) {
|
||||
vips__heif_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
return( VIPS_FOREIGN_LOAD_HEIF_CLASS(
|
||||
vips_foreign_load_heif_buffer_parent_class )->open( heif ) );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_heif_buffer_class_init(
|
||||
VipsForeignLoadHeifBufferClass *class )
|
||||
@ -1043,18 +1088,15 @@ vips_foreign_load_heif_buffer_class_init(
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
VipsForeignLoadHeifClass *heif_class =
|
||||
(VipsForeignLoadHeifClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "heifload_buffer";
|
||||
object_class->build = vips_foreign_load_heif_buffer_build;
|
||||
|
||||
load_class->is_a_buffer = vips_foreign_load_heif_buffer_is_a;
|
||||
|
||||
heif_class->open = vips_foreign_load_heif_buffer_open;
|
||||
|
||||
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||
_( "Buffer" ),
|
||||
_( "Buffer to load from" ),
|
||||
|
Loading…
Reference in New Issue
Block a user