Build a dynamically loadable module for OpenSlide

By default, a dynamically loadable module is built for OpenSlide (i.e.
`--with-openslide=module`) when:
* OpenSlide is found;
* GModule is supported (`gmodule_supported` pkg-config variable).

This can be overridden on the command line with:
* `--without-openslide` - to disable OpenSlide usage;
* `--with-openslide[=yes]` - to restore the previous behavior;
* `--disable-modules` - to disable the build of dynamic modules.
This commit is contained in:
Kleis Auke Wolthuizen 2021-03-27 18:42:53 +01:00
parent 5c54d13701
commit 6fd38df95a
9 changed files with 486 additions and 399 deletions

View File

@ -984,32 +984,44 @@ VIPS_LIBS="$VIPS_LIBS $ZLIB_LIBS"
# OpenSlide
AC_ARG_WITH([openslide],
AS_HELP_STRING([--without-openslide],
[build without OpenSlide (default: test)])
)
[build without OpenSlide (default: test)]),
[with_openslide=$withval],
[with_openslide=$gmodule_with_flag])
# OpenSlide as a dynamically loadable module
AS_IF([test x"$with_openslide" = x"module"],
[with_openslide_module=$gmodule_supported_flag],
[with_openslide_module=no])
if test x"$with_openslide" != x"no"; then
PKG_CHECK_MODULES(OPENSLIDE, [openslide >= 3.4.0],
[AC_DEFINE(HAVE_OPENSLIDE_3_4,1,[define if you have OpenSlide >= 3.4.0 installed.])
AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
with_openslide=yes
PACKAGES_USED="$PACKAGES_USED openslide"
AS_IF([test x"$with_openslide_module" = x"no"],
[PACKAGES_USED="$PACKAGES_USED openslide"])
],
[AC_MSG_NOTICE([OpenSlide >= 3.4.0 not found; checking for >= 3.3.0])
PKG_CHECK_MODULES(OPENSLIDE, [openslide >= 3.3.0],
[AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
with_openslide=yes
PACKAGES_USED="$PACKAGES_USED openslide"
AS_IF([test x"$with_openslide_module" = x"no"],
[PACKAGES_USED="$PACKAGES_USED openslide"])
],
[AC_MSG_WARN([OpenSlide >= 3.3.0 not found; disabling virtual slide support])
with_openslide=no
with_openslide_module=no
]
)
]
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $OPENSLIDE_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $OPENSLIDE_LIBS"
AS_IF([test x"$with_openslide_module" = x"yes"],
[AC_DEFINE([OPENSLIDE_MODULE], [1], [define to build OpenSlide as a dynamically loadable module.])],
[VIPS_CFLAGS="$VIPS_CFLAGS $OPENSLIDE_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $OPENSLIDE_LIBS"])
AM_CONDITIONAL(OPENSLIDE_MODULE, [test x"$with_openslide_module" = x"yes"])
# matio
AC_ARG_WITH([matio],
@ -1385,7 +1397,7 @@ PDF load with PDFium: $with_pdfium, \
PDF load with poppler-glib: $with_poppler, \
SVG load with librsvg-2.0: $with_rsvg, \
EXR load with OpenEXR: $with_OpenEXR, \
slide load with OpenSlide: $with_openslide, \
slide load with OpenSlide: $with_openslide (dynamic module: $with_openslide_module), \
Matlab load with matio: $with_matio, \
NIfTI load/save with niftiio: $with_nifti, \
FITS load/save with cfitsio: $with_cfitsio, \
@ -1500,7 +1512,7 @@ SVG load with librsvg-2.0: $with_rsvg
EXR load with OpenEXR: $with_OpenEXR
JPEG2000 load/save with libopenjp2: $with_libopenjp2
(requires libopenjp2 2.2 or later)
slide load with OpenSlide: $with_openslide
slide load with OpenSlide: $with_openslide (dynamic module: $with_openslide_module)
(requires openslide-3.3.0 or later)
Matlab load with matio: $with_matio
NIfTI load/save with niftiio: $with_nifti

View File

@ -82,6 +82,10 @@ module_LTLIBRARIES =
moduledir = @VIPS_LIBDIR@/vips-modules-@VIPS_MAJOR_VERSION@.@VIPS_MINOR_VERSION@
if OPENSLIDE_MODULE
module_LTLIBRARIES += vips-openslide.la
endif # OPENSLIDE_MODULE
MODULE_CPPFLAGS = \
-I${top_srcdir}/libvips/include \
$(REQUIRED_CFLAGS)
@ -100,6 +104,11 @@ MODULE_LIBADD = \
# dynamically loadable module. The C definitions are always
# included in the main library.
vips_openslide_la_SOURCES = module/openslide.c foreign/openslide2vips.c
vips_openslide_la_CPPFLAGS = $(MODULE_CPPFLAGS) $(OPENSLIDE_CFLAGS)
vips_openslide_la_LDFLAGS = $(MODULE_LDFLAGS)
vips_openslide_la_LIBADD = $(MODULE_LIBADD) $(OPENSLIDE_LIBS)
# Introspection
-include $(INTROSPECTION_MAKEFILE)

View File

@ -40,7 +40,6 @@ libforeign_la_SOURCES = \
nsgifload.c \
openexr2vips.c \
openexrload.c \
openslide2vips.c \
openslideload.c \
pdfiumload.c \
pdfload.c \
@ -75,6 +74,10 @@ libforeign_la_SOURCES = \
# We still need to include the GObject part of a loader/saver
# if it is not built as a dynamically loadable module.
if !OPENSLIDE_MODULE
libforeign_la_SOURCES += openslide2vips.c
endif # !OPENSLIDE_MODULE
EXTRA_DIST = libnsgif
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -2322,10 +2322,10 @@ vips_foreign_operation_init( void )
vips_foreign_save_tiff_buffer_get_type();
#endif /*HAVE_TIFF*/
#ifdef HAVE_OPENSLIDE
#if defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE)
vips_foreign_load_openslide_file_get_type();
vips_foreign_load_openslide_source_get_type();
#endif /*HAVE_OPENSLIDE*/
#endif /*defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE)*/
#ifdef ENABLE_MAGICKLOAD
#ifdef HAVE_MAGICK6

View File

@ -53,6 +53,8 @@
* - option to attach associated images as metadata
* 22/6/20 adamu
* - set libvips xres/yres from openslide mpp-x/mpp-y
* 13/2/21 kleisauke
* - include GObject part from openslideload.c
*/
/*
@ -126,7 +128,7 @@ typedef struct {
int tile_height;
} ReadSlide;
int
static int
vips__openslide_isslide( const char *filename )
{
#ifdef HAVE_OPENSLIDE_3_4
@ -543,7 +545,7 @@ readslide_parse( ReadSlide *rslide, VipsImage *image )
return( 0 );
}
int
static int
vips__openslide_read_header( const char *filename, VipsImage *out,
int level, gboolean autocrop,
char *associated, gboolean attach_associated )
@ -614,7 +616,7 @@ vips__openslide_generate( VipsRegion *out,
return( 0 );
}
int
static int
vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean autocrop, gboolean attach_associated )
{
@ -658,7 +660,7 @@ vips__openslide_read( const char *filename, VipsImage *out,
return( 0 );
}
int
static int
vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated )
{
@ -699,4 +701,373 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
return( 0 );
}
typedef struct _VipsForeignLoadOpenslide {
VipsForeignLoad parent_object;
/* Source to load from (set by subclasses).
*/
VipsSource *source;
/* Filename from source.
*/
const char *filename;
/* Load this level.
*/
int level;
/* Crop to image bounds.
*/
gboolean autocrop;
/* Load just this associated image.
*/
char *associated;
/* Attach all associated images as metadata items.
*/
gboolean attach_associated;
} VipsForeignLoadOpenslide;
typedef VipsForeignLoadClass VipsForeignLoadOpenslideClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadOpenslide, vips_foreign_load_openslide,
VIPS_TYPE_FOREIGN_LOAD );
static void
vips_foreign_load_openslide_dispose( GObject *gobject )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) gobject;
VIPS_UNREF( openslide->source );
G_OBJECT_CLASS( vips_foreign_load_openslide_parent_class )->
dispose( gobject );
}
static int
vips_foreign_load_openslide_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
/* We can only open source which have an associated filename, since
* the openslide library works in terms of filenames.
*/
if( openslide->source ) {
openslide->filename =
vips_connection_filename( VIPS_CONNECTION(
openslide->source ) );
if( !openslide->filename ) {
vips_error( class->nickname, "%s",
_( "no filename available" ) );
return( -1 );
}
}
if( VIPS_OBJECT_CLASS( vips_foreign_load_openslide_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags_source( VipsSource *source )
{
/* We can't tell from just the source, we need to know what part of
* the file the user wants. But it'll usually be partial.
*/
return( VIPS_FOREIGN_PARTIAL );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
VipsForeignFlags flags;
flags = 0;
if( !openslide->associated )
flags |= VIPS_FOREIGN_PARTIAL;
return( flags );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags_filename( const char *filename )
{
VipsSource *source;
VipsForeignFlags flags;
if( !(source = vips_source_new_from_file( filename )) )
return( 0 );
flags = vips_foreign_load_openslide_get_flags_source( source );
VIPS_UNREF( source );
return( flags );
}
static int
vips_foreign_load_openslide_header( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( vips__openslide_read_header( openslide->filename, load->out,
openslide->level, openslide->autocrop,
openslide->associated, openslide->attach_associated ) )
return( -1 );
VIPS_SETSTR( load->out->filename, openslide->filename );
return( 0 );
}
static int
vips_foreign_load_openslide_load( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( !openslide->associated ) {
if( vips__openslide_read( openslide->filename, load->real,
openslide->level, openslide->autocrop,
openslide->attach_associated ) )
return( -1 );
}
else {
if( vips__openslide_read_associated( openslide->filename,
load->real, openslide->associated ) )
return( -1 );
}
return( 0 );
}
static void
vips_foreign_load_openslide_class_init( VipsForeignLoadOpenslideClass *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->dispose = vips_foreign_load_openslide_dispose;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "openslideload_base";
object_class->description = _( "load OpenSlide base class" );
object_class->build = vips_foreign_load_openslide_build;
/* We need to be ahead of the tiff sniffer since many OpenSlide
* formats are tiff derivatives. If we see a tiff which would be
* better handled by the vips tiff loader we are careful to say no.
*
* We need to be ahead of JPEG, since MRXS images are also
* JPEGs.
*/
foreign_class->priority = 100;
load_class->get_flags_filename =
vips_foreign_load_openslide_get_flags_filename;
load_class->get_flags = vips_foreign_load_openslide_get_flags;
load_class->header = vips_foreign_load_openslide_header;
load_class->load = vips_foreign_load_openslide_load;
VIPS_ARG_INT( class, "level", 20,
_( "Level" ),
_( "Load this level from the file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, level ),
0, 100000, 0 );
VIPS_ARG_BOOL( class, "autocrop", 21,
_( "Autocrop" ),
_( "Crop to image bounds" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, autocrop ),
FALSE );
VIPS_ARG_STRING( class, "associated", 22,
_( "Associated" ),
_( "Load this associated image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, associated ),
NULL );
VIPS_ARG_BOOL( class, "attach-associated", 13,
_( "Attach associated" ),
_( "Attach all associated images" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, attach_associated ),
FALSE );
}
static void
vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide )
{
}
typedef struct _VipsForeignLoadOpenslideFile {
VipsForeignLoadOpenslide parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadOpenslideFile;
typedef VipsForeignLoadOpenslideClass VipsForeignLoadOpenslideFileClass;
G_DEFINE_TYPE( VipsForeignLoadOpenslideFile, vips_foreign_load_openslide_file,
vips_foreign_load_openslide_get_type() );
static int
vips_foreign_load_openslide_file_build( VipsObject *object )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
VipsForeignLoadOpenslideFile *file =
(VipsForeignLoadOpenslideFile *) object;
if( file->filename &&
!(openslide->source =
vips_source_new_from_file( file->filename )) )
return( -1 );
if( VIPS_OBJECT_CLASS( vips_foreign_load_openslide_file_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static const char *vips_foreign_openslide_suffs[] = {
".svs", /* Aperio */
".vms", ".vmu", ".ndpi", /* Hamamatsu */
".scn", /* Leica */
".mrxs", /* MIRAX */
".svslide", /* Sakura */
".tif", /* Trestle */
".bif", /* Ventana */
NULL
};
static void
vips_foreign_load_openslide_file_class_init(
VipsForeignLoadOpenslideFileClass *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 = "openslideload";
object_class->description = _( "load file with OpenSlide" );
object_class->build = vips_foreign_load_openslide_file_build;
foreign_class->suffs = vips_foreign_openslide_suffs;
load_class->is_a = vips__openslide_isslide;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslideFile, filename ),
NULL );
}
static void
vips_foreign_load_openslide_file_init( VipsForeignLoadOpenslideFile *openslide )
{
}
typedef struct _VipsForeignLoadOpenslideSource {
VipsForeignLoadOpenslide parent_object;
/* Load from a source.
*/
VipsSource *source;
} VipsForeignLoadOpenslideSource;
typedef VipsForeignLoadOpenslideClass VipsForeignLoadOpenslideSourceClass;
G_DEFINE_TYPE( VipsForeignLoadOpenslideSource,
vips_foreign_load_openslide_source,
vips_foreign_load_openslide_get_type() );
static int
vips_foreign_load_openslide_source_build( VipsObject *object )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
VipsForeignLoadOpenslideSource *source =
(VipsForeignLoadOpenslideSource *) object;
if( source->source ) {
openslide->source = source->source;
g_object_ref( openslide->source );
}
if( VIPS_OBJECT_CLASS(
vips_foreign_load_openslide_source_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static gboolean
vips_foreign_load_openslide_source_is_a_source( VipsSource *source )
{
const char *filename;
return( (filename =
vips_connection_filename( VIPS_CONNECTION( source ) )) &&
vips__openslide_isslide( filename ) );
}
static void
vips_foreign_load_openslide_source_class_init(
VipsForeignLoadOpenslideSourceClass *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 = "openslideload_source";
object_class->description = _( "load source with OpenSlide" );
object_class->build = vips_foreign_load_openslide_source_build;
load_class->is_a_source =
vips_foreign_load_openslide_source_is_a_source;
VIPS_ARG_OBJECT( class, "source", 1,
_( "Source" ),
_( "Source to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslideSource, source ),
VIPS_TYPE_SOURCE );
}
static void
vips_foreign_load_openslide_source_init(
VipsForeignLoadOpenslideSource *openslide )
{
}
#endif /*HAVE_OPENSLIDE*/

View File

@ -11,6 +11,8 @@
* - drop glib log handler (unneeded with >= 3.3.0)
* 27/1/18
* - option to attach associated images as metadata
* 13/2/21 kleisauke
* - move GObject part to openslide2vips.c
*/
/*
@ -57,381 +59,6 @@
#include <vips/buf.h>
#include <vips/internal.h>
#include "pforeign.h"
#ifdef HAVE_OPENSLIDE
typedef struct _VipsForeignLoadOpenslide {
VipsForeignLoad parent_object;
/* Source to load from (set by subclasses).
*/
VipsSource *source;
/* Filename from source.
*/
const char *filename;
/* Load this level.
*/
int level;
/* Crop to image bounds.
*/
gboolean autocrop;
/* Load just this associated image.
*/
char *associated;
/* Attach all associated images as metadata items.
*/
gboolean attach_associated;
} VipsForeignLoadOpenslide;
typedef VipsForeignLoadClass VipsForeignLoadOpenslideClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadOpenslide, vips_foreign_load_openslide,
VIPS_TYPE_FOREIGN_LOAD );
static void
vips_foreign_load_openslide_dispose( GObject *gobject )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) gobject;
VIPS_UNREF( openslide->source );
G_OBJECT_CLASS( vips_foreign_load_openslide_parent_class )->
dispose( gobject );
}
static int
vips_foreign_load_openslide_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
/* We can only open source which have an associated filename, since
* the openslide library works in terms of filenames.
*/
if( openslide->source ) {
openslide->filename =
vips_connection_filename( VIPS_CONNECTION(
openslide->source ) );
if( !openslide->filename ) {
vips_error( class->nickname, "%s",
_( "no filename available" ) );
return( -1 );
}
}
if( VIPS_OBJECT_CLASS( vips_foreign_load_openslide_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags_source( VipsSource *source )
{
/* We can't tell from just the source, we need to know what part of
* the file the user wants. But it'll usually be partial.
*/
return( VIPS_FOREIGN_PARTIAL );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
VipsForeignFlags flags;
flags = 0;
if( !openslide->associated )
flags |= VIPS_FOREIGN_PARTIAL;
return( flags );
}
static VipsForeignFlags
vips_foreign_load_openslide_get_flags_filename( const char *filename )
{
VipsSource *source;
VipsForeignFlags flags;
if( !(source = vips_source_new_from_file( filename )) )
return( 0 );
flags = vips_foreign_load_openslide_get_flags_source( source );
VIPS_UNREF( source );
return( flags );
}
static int
vips_foreign_load_openslide_header( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( vips__openslide_read_header( openslide->filename, load->out,
openslide->level, openslide->autocrop,
openslide->associated, openslide->attach_associated ) )
return( -1 );
VIPS_SETSTR( load->out->filename, openslide->filename );
return( 0 );
}
static int
vips_foreign_load_openslide_load( VipsForeignLoad *load )
{
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( !openslide->associated ) {
if( vips__openslide_read( openslide->filename, load->real,
openslide->level, openslide->autocrop,
openslide->attach_associated ) )
return( -1 );
}
else {
if( vips__openslide_read_associated( openslide->filename,
load->real, openslide->associated ) )
return( -1 );
}
return( 0 );
}
static void
vips_foreign_load_openslide_class_init( VipsForeignLoadOpenslideClass *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->dispose = vips_foreign_load_openslide_dispose;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "openslideload_base";
object_class->description = _( "load OpenSlide base class" );
object_class->build = vips_foreign_load_openslide_build;
/* We need to be ahead of the tiff sniffer since many OpenSlide
* formats are tiff derivatives. If we see a tiff which would be
* better handled by the vips tiff loader we are careful to say no.
*
* We need to be ahead of JPEG, since MRXS images are also
* JPEGs.
*/
foreign_class->priority = 100;
load_class->get_flags_filename =
vips_foreign_load_openslide_get_flags_filename;
load_class->get_flags = vips_foreign_load_openslide_get_flags;
load_class->header = vips_foreign_load_openslide_header;
load_class->load = vips_foreign_load_openslide_load;
VIPS_ARG_INT( class, "level", 20,
_( "Level" ),
_( "Load this level from the file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, level ),
0, 100000, 0 );
VIPS_ARG_BOOL( class, "autocrop", 21,
_( "Autocrop" ),
_( "Crop to image bounds" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, autocrop ),
FALSE );
VIPS_ARG_STRING( class, "associated", 22,
_( "Associated" ),
_( "Load this associated image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, associated ),
NULL );
VIPS_ARG_BOOL( class, "attach-associated", 13,
_( "Attach associated" ),
_( "Attach all associated images" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, attach_associated ),
FALSE );
}
static void
vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide )
{
}
typedef struct _VipsForeignLoadOpenslideFile {
VipsForeignLoadOpenslide parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadOpenslideFile;
typedef VipsForeignLoadOpenslideClass VipsForeignLoadOpenslideFileClass;
G_DEFINE_TYPE( VipsForeignLoadOpenslideFile, vips_foreign_load_openslide_file,
vips_foreign_load_openslide_get_type() );
static int
vips_foreign_load_openslide_file_build( VipsObject *object )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
VipsForeignLoadOpenslideFile *file =
(VipsForeignLoadOpenslideFile *) object;
if( file->filename &&
!(openslide->source =
vips_source_new_from_file( file->filename )) )
return( -1 );
if( VIPS_OBJECT_CLASS( vips_foreign_load_openslide_file_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static const char *vips_foreign_openslide_suffs[] = {
".svs", /* Aperio */
".vms", ".vmu", ".ndpi", /* Hamamatsu */
".scn", /* Leica */
".mrxs", /* MIRAX */
".svslide", /* Sakura */
".tif", /* Trestle */
".bif", /* Ventana */
NULL
};
static void
vips_foreign_load_openslide_file_class_init(
VipsForeignLoadOpenslideFileClass *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 = "openslideload";
object_class->description = _( "load file with OpenSlide" );
object_class->build = vips_foreign_load_openslide_file_build;
foreign_class->suffs = vips_foreign_openslide_suffs;
load_class->is_a = vips__openslide_isslide;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslideFile, filename ),
NULL );
}
static void
vips_foreign_load_openslide_file_init( VipsForeignLoadOpenslideFile *openslide )
{
}
typedef struct _VipsForeignLoadOpenslideSource {
VipsForeignLoadOpenslide parent_object;
/* Load from a source.
*/
VipsSource *source;
} VipsForeignLoadOpenslideSource;
typedef VipsForeignLoadOpenslideClass VipsForeignLoadOpenslideSourceClass;
G_DEFINE_TYPE( VipsForeignLoadOpenslideSource,
vips_foreign_load_openslide_source,
vips_foreign_load_openslide_get_type() );
static int
vips_foreign_load_openslide_source_build( VipsObject *object )
{
VipsForeignLoadOpenslide *openslide =
(VipsForeignLoadOpenslide *) object;
VipsForeignLoadOpenslideSource *source =
(VipsForeignLoadOpenslideSource *) object;
if( source->source ) {
openslide->source = source->source;
g_object_ref( openslide->source );
}
if( VIPS_OBJECT_CLASS(
vips_foreign_load_openslide_source_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static gboolean
vips_foreign_load_openslide_source_is_a_source( VipsSource *source )
{
const char *filename;
return( (filename =
vips_connection_filename( VIPS_CONNECTION( source ) )) &&
vips__openslide_isslide( filename ) );
}
static void
vips_foreign_load_openslide_source_class_init(
VipsForeignLoadOpenslideSourceClass *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 = "openslideload_source";
object_class->description = _( "load source with OpenSlide" );
object_class->build = vips_foreign_load_openslide_source_build;
load_class->is_a_source =
vips_foreign_load_openslide_source_is_a_source;
VIPS_ARG_OBJECT( class, "source", 1,
_( "Source" ),
_( "Source to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslideSource, source ),
VIPS_TYPE_SOURCE );
}
static void
vips_foreign_load_openslide_source_init(
VipsForeignLoadOpenslideSource *openslide )
{
}
#endif /*HAVE_OPENSLIDE*/
/**
* vips_openslideload:
* @filename: file to load

View File

@ -213,15 +213,6 @@ int vips__webp_write_target( VipsImage *image, VipsTarget *target,
gboolean min_size, int kmin, int kmax,
gboolean strip, const char *profile );
int vips__openslide_isslide( const char *filename );
int vips__openslide_read_header( const char *filename, VipsImage *out,
int level, gboolean autocrop,
char *associated, gboolean attach_associated );
int vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean autocrop, gboolean attach_associated );
int vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated );
gboolean vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len );
gboolean vips_foreign_load_pdf_is_a( const char *filename );

View File

@ -0,0 +1,74 @@
/* openslide as a dynamically loadable module
*
* 11/2/21 kleisauke
* - initial
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/debug.h>
#include <vips/internal.h>
#if defined(HAVE_OPENSLIDE) && defined(OPENSLIDE_MODULE)
/* This is called on module load.
*/
G_MODULE_EXPORT const gchar *
g_module_check_init( GModule *module )
{
#ifdef DEBUG
printf( "vips_openslide: module init\n" );
#endif /*DEBUG*/
extern GType vips_foreign_load_openslide_file_get_type( void );
extern GType vips_foreign_load_openslide_source_get_type( void );
vips_foreign_load_openslide_file_get_type();
vips_foreign_load_openslide_source_get_type();
/* We can't be unloaded, there would be chaos.
*/
g_module_make_resident( module );
return( NULL );
}
#endif /*defined(HAVE_OPENSLIDE) && defined(OPENSLIDE_MODULE)*/