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:
parent
5c54d13701
commit
6fd38df95a
28
configure.ac
28
configure.ac
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
||||
|
74
libvips/module/openslide.c
Normal file
74
libvips/module/openslide.c
Normal 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)*/
|
Loading…
x
Reference in New Issue
Block a user