Merge pull request #2156 from libvips/add-openjpeg
Add JPEG2000 support
This commit is contained in:
commit
cb660b32fe
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -56,6 +56,7 @@ jobs:
|
|||||||
liblcms2-dev libpoppler-glib-dev librsvg2-dev
|
liblcms2-dev libpoppler-glib-dev librsvg2-dev
|
||||||
libgif-dev libopenexr-dev libpango1.0-dev
|
libgif-dev libopenexr-dev libpango1.0-dev
|
||||||
libgsf-1-dev libopenslide-dev libffi-dev
|
libgsf-1-dev libopenslide-dev libffi-dev
|
||||||
|
libopenjp2-7-dev
|
||||||
|
|
||||||
- name: Install macOS dependencies
|
- name: Install macOS dependencies
|
||||||
if: contains(matrix.os, 'macos')
|
if: contains(matrix.os, 'macos')
|
||||||
@ -69,6 +70,7 @@ jobs:
|
|||||||
librsvg libspng libtiff
|
librsvg libspng libtiff
|
||||||
little-cms2 openexr openslide
|
little-cms2 openexr openslide
|
||||||
orc pango poppler webp
|
orc pango poppler webp
|
||||||
|
openjpeg
|
||||||
|
|
||||||
- name: Install Clang 10
|
- name: Install Clang 10
|
||||||
env:
|
env:
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
- add vips_fitsload_source(), vips_niftiload_source()
|
- add vips_fitsload_source(), vips_niftiload_source()
|
||||||
- png and gif load note background colour as metadata [781545872]
|
- png and gif load note background colour as metadata [781545872]
|
||||||
- add vips_image_[set|get]_array_double()
|
- add vips_image_[set|get]_array_double()
|
||||||
|
- add GIF load with libnsgif
|
||||||
|
- add JPEG2000 load and save
|
||||||
|
|
||||||
22/12/20 start 8.10.6
|
22/12/20 start 8.10.6
|
||||||
- don't seek on bad file descriptors [kleisauke]
|
- don't seek on bad file descriptors [kleisauke]
|
||||||
|
32
configure.ac
32
configure.ac
@ -770,6 +770,36 @@ VIPS_CFLAGS="$VIPS_CFLAGS $NIFTI_CFLAGS"
|
|||||||
VIPS_INCLUDES="$VIPS_INCLUDES $NIFTI_INCLUDES"
|
VIPS_INCLUDES="$VIPS_INCLUDES $NIFTI_INCLUDES"
|
||||||
VIPS_LIBS="$VIPS_LIBS $NIFTI_LIBS"
|
VIPS_LIBS="$VIPS_LIBS $NIFTI_LIBS"
|
||||||
|
|
||||||
|
# openjpeg
|
||||||
|
AC_ARG_WITH([libopenjp2],
|
||||||
|
AS_HELP_STRING([--without-libopenjp2],
|
||||||
|
[build without libopenjp2 (default: test)]))
|
||||||
|
|
||||||
|
if test x"$with_libopenjp2" != x"no"; then
|
||||||
|
PKG_CHECK_MODULES(LIBOPENJP2, libopenjp2 >= 2.3,
|
||||||
|
[AC_DEFINE(HAVE_LIBOPENJP2,1,
|
||||||
|
[define if you have libopenjp2 >=2.2 installed.])
|
||||||
|
with_libopenjp2=yes
|
||||||
|
PACKAGES_USED="$PACKAGES_USED libopenjp2"
|
||||||
|
],
|
||||||
|
[AC_MSG_WARN([libopenjp2 not found; disabling libopenjp2 support])
|
||||||
|
with_libopenjp2=no
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2.3 and earlier have threading problems
|
||||||
|
PKG_CHECK_MODULES(LIBOPENJP2_THREADING, libopenjp2 >= 2.4,
|
||||||
|
[AC_DEFINE(HAVE_LIBOPENJP2_THREADING,1,[define if your libopenjp2 threading works.])
|
||||||
|
],
|
||||||
|
[:
|
||||||
|
]
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
VIPS_CFLAGS="$VIPS_CFLAGS $LIBOPENJP2_CFLAGS"
|
||||||
|
VIPS_INCLUDES="$VIPS_INCLUDES $LIBOPENJP2_INCLUDES"
|
||||||
|
VIPS_LIBS="$VIPS_LIBS $LIBOPENJP2_LIBS"
|
||||||
|
|
||||||
# libheif
|
# libheif
|
||||||
AC_ARG_WITH([heif],
|
AC_ARG_WITH([heif],
|
||||||
AS_HELP_STRING([--without-heif], [build without libheif (default: test)]))
|
AS_HELP_STRING([--without-heif], [build without libheif (default: test)]))
|
||||||
@ -1420,6 +1450,8 @@ PDF load with poppler-glib: $with_poppler
|
|||||||
SVG load with librsvg-2.0: $with_rsvg
|
SVG load with librsvg-2.0: $with_rsvg
|
||||||
(requires librsvg-2.0 2.34.0 or later)
|
(requires librsvg-2.0 2.34.0 or later)
|
||||||
EXR load with OpenEXR: $with_OpenEXR
|
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
|
||||||
(requires openslide-3.3.0 or later)
|
(requires openslide-3.3.0 or later)
|
||||||
Matlab load with matio: $with_matio
|
Matlab load with matio: $with_matio
|
||||||
|
@ -263,12 +263,6 @@ TAB_SIZE = 8
|
|||||||
|
|
||||||
ALIASES =
|
ALIASES =
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
|
||||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
|
||||||
# will allow you to use the command class in the itcl::class meaning.
|
|
||||||
|
|
||||||
TCL_SUBST =
|
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
# instance, some of the names that are used will be different. The list of all
|
# instance, some of the names that are used will be different. The list of all
|
||||||
|
@ -5,70 +5,72 @@ endif
|
|||||||
noinst_LTLIBRARIES = libforeign.la
|
noinst_LTLIBRARIES = libforeign.la
|
||||||
|
|
||||||
libforeign_la_SOURCES = \
|
libforeign_la_SOURCES = \
|
||||||
pforeign.h \
|
analyze2vips.c \
|
||||||
heifload.c \
|
analyzeload.c \
|
||||||
heifsave.c \
|
|
||||||
niftiload.c \
|
|
||||||
niftisave.c \
|
|
||||||
quantise.c \
|
|
||||||
exif.c \
|
|
||||||
nsgifload.c \
|
|
||||||
cairo.c \
|
cairo.c \
|
||||||
pdfload.c \
|
|
||||||
pdfiumload.c \
|
|
||||||
svgload.c \
|
|
||||||
radiance.c \
|
|
||||||
radload.c \
|
|
||||||
radsave.c \
|
|
||||||
ppmload.c \
|
|
||||||
ppmsave.c \
|
|
||||||
csvload.c \
|
csvload.c \
|
||||||
csvsave.c \
|
csvsave.c \
|
||||||
matrixload.c \
|
|
||||||
matrixsave.c \
|
|
||||||
dzsave.c \
|
|
||||||
rawload.c \
|
|
||||||
rawsave.c \
|
|
||||||
vipsload.c \
|
|
||||||
vipssave.c \
|
|
||||||
dbh.h \
|
dbh.h \
|
||||||
analyzeload.c \
|
dzsave.c \
|
||||||
analyze2vips.c \
|
exif.c \
|
||||||
foreign.c \
|
|
||||||
matlab.c \
|
|
||||||
matload.c \
|
|
||||||
magick.h \
|
|
||||||
magick.c \
|
|
||||||
magick2vips.c \
|
|
||||||
magickload.c \
|
|
||||||
magick7load.c \
|
|
||||||
magicksave.c \
|
|
||||||
spngload.c \
|
|
||||||
pngload.c \
|
|
||||||
pngsave.c \
|
|
||||||
vipspng.c \
|
|
||||||
openexr2vips.c \
|
|
||||||
openexrload.c \
|
|
||||||
fits.c \
|
fits.c \
|
||||||
fitsload.c \
|
fitsload.c \
|
||||||
fitssave.c \
|
fitssave.c \
|
||||||
tiff.h \
|
foreign.c \
|
||||||
tiff.c \
|
heifload.c \
|
||||||
vips2tiff.c \
|
heifsave.c \
|
||||||
tiff2vips.c \
|
jp2kload.c \
|
||||||
tiffload.c \
|
jp2ksave.c \
|
||||||
tiffsave.c \
|
|
||||||
openslide2vips.c \
|
|
||||||
openslideload.c \
|
|
||||||
webpload.c \
|
|
||||||
webpsave.c \
|
|
||||||
webp2vips.c \
|
|
||||||
vips2webp.c \
|
|
||||||
vips2jpeg.c \
|
|
||||||
jpeg2vips.c \
|
jpeg2vips.c \
|
||||||
jpeg.h \
|
jpeg.h \
|
||||||
jpegload.c \
|
jpegload.c \
|
||||||
jpegsave.c
|
jpegsave.c \
|
||||||
|
magick2vips.c \
|
||||||
|
magick7load.c \
|
||||||
|
magick.c \
|
||||||
|
magick.h \
|
||||||
|
magickload.c \
|
||||||
|
magicksave.c \
|
||||||
|
matlab.c \
|
||||||
|
matload.c \
|
||||||
|
matrixload.c \
|
||||||
|
matrixsave.c \
|
||||||
|
niftiload.c \
|
||||||
|
niftisave.c \
|
||||||
|
nsgifload.c \
|
||||||
|
openexr2vips.c \
|
||||||
|
openexrload.c \
|
||||||
|
openslide2vips.c \
|
||||||
|
openslideload.c \
|
||||||
|
pdfiumload.c \
|
||||||
|
pdfload.c \
|
||||||
|
pforeign.h \
|
||||||
|
pngload.c \
|
||||||
|
pngsave.c \
|
||||||
|
ppmload.c \
|
||||||
|
ppmsave.c \
|
||||||
|
quantise.c \
|
||||||
|
radiance.c \
|
||||||
|
radload.c \
|
||||||
|
radsave.c \
|
||||||
|
rawload.c \
|
||||||
|
rawsave.c \
|
||||||
|
spngload.c \
|
||||||
|
svgload.c \
|
||||||
|
tiff2vips.c \
|
||||||
|
tiff.c \
|
||||||
|
tiff.h \
|
||||||
|
tiffload.c \
|
||||||
|
tiffsave.c \
|
||||||
|
vips2jpeg.c \
|
||||||
|
vips2tiff.c \
|
||||||
|
vips2webp.c \
|
||||||
|
vipsload.c \
|
||||||
|
vipspng.c \
|
||||||
|
vipssave.c \
|
||||||
|
webp2vips.c \
|
||||||
|
webpload.c \
|
||||||
|
webpsave.c
|
||||||
|
|
||||||
EXTRA_DIST = libnsgif
|
EXTRA_DIST = libnsgif
|
||||||
|
|
||||||
|
@ -2176,6 +2176,13 @@ vips_foreign_operation_init( void )
|
|||||||
extern GType vips_foreign_load_svg_buffer_get_type( void );
|
extern GType vips_foreign_load_svg_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_svg_source_get_type( void );
|
extern GType vips_foreign_load_svg_source_get_type( void );
|
||||||
|
|
||||||
|
extern GType vips_foreign_load_jp2k_file_get_type( void );
|
||||||
|
extern GType vips_foreign_load_jp2k_buffer_get_type( void );
|
||||||
|
extern GType vips_foreign_load_jp2k_source_get_type( void );
|
||||||
|
extern GType vips_foreign_save_jp2k_file_get_type( void );
|
||||||
|
extern GType vips_foreign_save_jp2k_buffer_get_type( void );
|
||||||
|
extern GType vips_foreign_save_jp2k_target_get_type( void );
|
||||||
|
|
||||||
extern GType vips_foreign_load_heif_file_get_type( void );
|
extern GType vips_foreign_load_heif_file_get_type( void );
|
||||||
extern GType vips_foreign_load_heif_buffer_get_type( void );
|
extern GType vips_foreign_load_heif_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_heif_source_get_type( void );
|
extern GType vips_foreign_load_heif_source_get_type( void );
|
||||||
@ -2249,8 +2256,17 @@ vips_foreign_operation_init( void )
|
|||||||
vips_foreign_load_svg_source_get_type();
|
vips_foreign_load_svg_source_get_type();
|
||||||
#endif /*HAVE_RSVG*/
|
#endif /*HAVE_RSVG*/
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBOPENJP2
|
||||||
|
vips_foreign_load_jp2k_file_get_type();
|
||||||
|
vips_foreign_load_jp2k_buffer_get_type();
|
||||||
|
vips_foreign_load_jp2k_source_get_type();
|
||||||
|
vips_foreign_save_jp2k_file_get_type();
|
||||||
|
vips_foreign_save_jp2k_buffer_get_type();
|
||||||
|
vips_foreign_save_jp2k_target_get_type();
|
||||||
|
#endif /*HAVE_LIBOPENJP2*/
|
||||||
|
|
||||||
#ifdef HAVE_NSGIF
|
#ifdef HAVE_NSGIF
|
||||||
vips_foreign_load_nsgif_file_get_type();
|
vips_foreign_load_nsgif_file_get_type();
|
||||||
vips_foreign_load_nsgif_buffer_get_type();
|
vips_foreign_load_nsgif_buffer_get_type();
|
||||||
vips_foreign_load_nsgif_source_get_type();
|
vips_foreign_load_nsgif_source_get_type();
|
||||||
#endif /*HAVE_NSGIF*/
|
#endif /*HAVE_NSGIF*/
|
||||||
|
@ -230,7 +230,8 @@ vips_foreign_load_heif_build( VipsObject *object )
|
|||||||
printf( "vips_foreign_load_heif_build:\n" );
|
printf( "vips_foreign_load_heif_build:\n" );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( vips_source_rewind( heif->source ) )
|
if( heif->source &&
|
||||||
|
vips_source_rewind( heif->source ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( !heif->ctx ) {
|
if( !heif->ctx ) {
|
||||||
@ -245,7 +246,6 @@ vips_foreign_load_heif_build( VipsObject *object )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -253,7 +253,6 @@ vips_foreign_load_heif_build( VipsObject *object )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *heif_magic[] = {
|
static const char *heif_magic[] = {
|
||||||
"ftypheic", /* A regular heif image */
|
"ftypheic", /* A regular heif image */
|
||||||
"ftypheix", /* Extended range (>8 bit) image */
|
"ftypheix", /* Extended range (>8 bit) image */
|
||||||
|
@ -380,7 +380,7 @@ vips_foreign_save_heif_build( VipsObject *object )
|
|||||||
|
|
||||||
chroma = heif->subsample_mode == VIPS_FOREIGN_SUBSAMPLE_OFF ||
|
chroma = heif->subsample_mode == VIPS_FOREIGN_SUBSAMPLE_OFF ||
|
||||||
( heif->subsample_mode == VIPS_FOREIGN_SUBSAMPLE_AUTO &&
|
( heif->subsample_mode == VIPS_FOREIGN_SUBSAMPLE_AUTO &&
|
||||||
heif->Q > 90 ) ? "444" : "420";
|
heif->Q >= 90 ) ? "444" : "420";
|
||||||
error = heif_encoder_set_parameter_string( heif->encoder,
|
error = heif_encoder_set_parameter_string( heif->encoder,
|
||||||
"chroma", chroma );
|
"chroma", chroma );
|
||||||
if( error.code &&
|
if( error.code &&
|
||||||
@ -738,7 +738,7 @@ vips_foreign_save_heif_target_init( VipsForeignSaveHeifTarget *target )
|
|||||||
* Use @speed to control the CPU effort spent improving compression.
|
* Use @speed to control the CPU effort spent improving compression.
|
||||||
* This is currently only applicable to AV1 encoders, defaults to 5.
|
* This is currently only applicable to AV1 encoders, defaults to 5.
|
||||||
*
|
*
|
||||||
* Chroma subsampling is normally automatically disabled for Q > 90. You can
|
* Chroma subsampling is normally automatically disabled for Q >= 90. You can
|
||||||
* force the subsampling mode with @subsample_mode.
|
* force the subsampling mode with @subsample_mode.
|
||||||
*
|
*
|
||||||
* See also: vips_image_write_to_file(), vips_heifload().
|
* See also: vips_image_write_to_file(), vips_heifload().
|
||||||
|
1233
libvips/foreign/jp2kload.c
Normal file
1233
libvips/foreign/jp2kload.c
Normal file
File diff suppressed because it is too large
Load Diff
1181
libvips/foreign/jp2ksave.c
Normal file
1181
libvips/foreign/jp2ksave.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -557,7 +557,7 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime )
|
|||||||
* If @strip is set, no EXIF data, IPTC data, ICC profile or XMP metadata is
|
* If @strip is set, no EXIF data, IPTC data, ICC profile or XMP metadata is
|
||||||
* written into the output file.
|
* written into the output file.
|
||||||
*
|
*
|
||||||
* Chroma subsampling is normally automatically disabled for Q > 90. You can
|
* Chroma subsampling is normally automatically disabled for Q >= 90. You can
|
||||||
* force the subsampling mode with @subsample_mode.
|
* force the subsampling mode with @subsample_mode.
|
||||||
*
|
*
|
||||||
* If @trellis_quant is set and the version of libjpeg supports it
|
* If @trellis_quant is set and the version of libjpeg supports it
|
||||||
|
@ -245,6 +245,8 @@ void vips__heif_error( struct heif_error *error );
|
|||||||
struct heif_image;
|
struct heif_image;
|
||||||
void vips__heif_image_print( struct heif_image *img );
|
void vips__heif_image_print( struct heif_image *img );
|
||||||
|
|
||||||
|
extern const char *vips__jp2k_suffs[];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -372,7 +372,7 @@ int vips_openslideload_source( VipsSource *source, VipsImage **out, ... )
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* VipsForeignSubsample:
|
* VipsForeignSubsample:
|
||||||
* @VIPS_FOREIGN_SUBSAMPLE_AUTO: prevent subsampling when quality > 90
|
* @VIPS_FOREIGN_SUBSAMPLE_AUTO: prevent subsampling when quality >= 90
|
||||||
* @VIPS_FOREIGN_SUBSAMPLE_ON: always perform subsampling
|
* @VIPS_FOREIGN_SUBSAMPLE_ON: always perform subsampling
|
||||||
* @VIPS_FOREIGN_SUBSAMPLE_OFF: never perform subsampling
|
* @VIPS_FOREIGN_SUBSAMPLE_OFF: never perform subsampling
|
||||||
*
|
*
|
||||||
@ -676,6 +676,19 @@ int vips_niftiload_source( VipsSource *source, VipsImage **out, ... )
|
|||||||
int vips_niftisave( VipsImage *in, const char *filename, ... )
|
int vips_niftisave( VipsImage *in, const char *filename, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
|
||||||
|
int vips_jp2kload( const char *filename, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_jp2kload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_jp2kload_source( VipsSource *source, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_jp2ksave( VipsImage *in, const char *filename, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_jp2ksave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
int vips_jp2ksave_target( VipsImage *in, VipsTarget *target, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VipsForeignDzLayout:
|
* VipsForeignDzLayout:
|
||||||
* @VIPS_FOREIGN_DZ_LAYOUT_DZ: use DeepZoom directory layout
|
* @VIPS_FOREIGN_DZ_LAYOUT_DZ: use DeepZoom directory layout
|
||||||
|
@ -136,11 +136,11 @@ typedef struct _VipsThumbnail {
|
|||||||
int heif_thumbnail_width;
|
int heif_thumbnail_width;
|
||||||
int heif_thumbnail_height;
|
int heif_thumbnail_height;
|
||||||
|
|
||||||
/* For TIFF sources, open subifds to get pyr layers.
|
/* Pyramids are stored in subifds.
|
||||||
*/
|
*/
|
||||||
gboolean subifd_pyramid;
|
gboolean subifd_pyramid;
|
||||||
|
|
||||||
/* For TIFF sources, open pages to get pyr layers.
|
/* Pyramids are stored in pages.
|
||||||
*/
|
*/
|
||||||
gboolean page_pyramid;
|
gboolean page_pyramid;
|
||||||
|
|
||||||
@ -250,18 +250,18 @@ vips_thumbnail_read_header( VipsThumbnail *thumbnail, VipsImage *image )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detect a TIFF pyramid made of pages following a roughly /2 shrink.
|
/* Detect a pyramid made of pages following a roughly /2 shrink.
|
||||||
*
|
*
|
||||||
* This may not be a pyr tiff, so no error if we can't find the layers.
|
* This may not be a pyr tiff, so no error if we can't find the layers.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vips_thumbnail_get_tiff_pyramid_page( VipsThumbnail *thumbnail )
|
vips_thumbnail_get_pyramid_page( VipsThumbnail *thumbnail )
|
||||||
{
|
{
|
||||||
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips_thumbnail_get_tiff_pyramid_page:\n" );
|
printf( "vips_thumbnail_get_pyramid_page:\n" );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
/* Single-page docs can't be pyramids.
|
/* Single-page docs can't be pyramids.
|
||||||
@ -301,7 +301,7 @@ vips_thumbnail_get_tiff_pyramid_page( VipsThumbnail *thumbnail )
|
|||||||
/* Now set level_count. This signals that we've found a pyramid.
|
/* Now set level_count. This signals that we've found a pyramid.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips_thumbnail_get_tiff_pyramid_page: "
|
printf( "vips_thumbnail_get_pyramid_page: "
|
||||||
"%d layer pyramid detected\n",
|
"%d layer pyramid detected\n",
|
||||||
thumbnail->n_pages );
|
thumbnail->n_pages );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
@ -500,7 +500,7 @@ vips_thumbnail_find_jpegshrink( VipsThumbnail *thumbnail,
|
|||||||
return( 1 );
|
return( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the best pyramid (openslide or tiff) level.
|
/* Find the best pyramid (openslide, tiff, etc.) level.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
vips_thumbnail_find_pyrlevel( VipsThumbnail *thumbnail,
|
vips_thumbnail_find_pyrlevel( VipsThumbnail *thumbnail,
|
||||||
@ -553,7 +553,21 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
thumbnail->subifd_pyramid = FALSE;
|
thumbnail->subifd_pyramid = FALSE;
|
||||||
thumbnail->page_pyramid = TRUE;
|
thumbnail->page_pyramid = TRUE;
|
||||||
|
|
||||||
vips_thumbnail_get_tiff_pyramid_page( thumbnail );
|
vips_thumbnail_get_pyramid_page( thumbnail );
|
||||||
|
|
||||||
|
if( thumbnail->level_count == 0 )
|
||||||
|
thumbnail->page_pyramid = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jp2k uses page-based pyramids.
|
||||||
|
*/
|
||||||
|
if( vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ) {
|
||||||
|
if( thumbnail->level_count == 0 ) {
|
||||||
|
thumbnail->subifd_pyramid = FALSE;
|
||||||
|
thumbnail->page_pyramid = TRUE;
|
||||||
|
|
||||||
|
vips_thumbnail_get_pyramid_page( thumbnail );
|
||||||
|
|
||||||
if( thumbnail->level_count == 0 )
|
if( thumbnail->level_count == 0 )
|
||||||
thumbnail->page_pyramid = FALSE;
|
thumbnail->page_pyramid = FALSE;
|
||||||
@ -576,8 +590,9 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
factor = vips_thumbnail_find_jpegshrink( thumbnail,
|
factor = vips_thumbnail_find_jpegshrink( thumbnail,
|
||||||
thumbnail->input_width, thumbnail->input_height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ||
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ||
|
||||||
|
vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ||
|
||||||
vips_isprefix( "VipsForeignLoadOpenslide",
|
vips_isprefix( "VipsForeignLoadOpenslide",
|
||||||
thumbnail->loader ) ) {
|
thumbnail->loader ) ) {
|
||||||
if( thumbnail->level_count > 0 )
|
if( thumbnail->level_count > 0 )
|
||||||
factor = vips_thumbnail_find_pyrlevel( thumbnail,
|
factor = vips_thumbnail_find_pyrlevel( thumbnail,
|
||||||
thumbnail->input_width,
|
thumbnail->input_width,
|
||||||
@ -1112,7 +1127,19 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"scale", 1.0 / factor,
|
"scale", 1.0 / factor,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
else if( vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ) {
|
||||||
|
/* jp2k optionally uses page-based pyramids.
|
||||||
|
*/
|
||||||
|
if( thumbnail->page_pyramid )
|
||||||
|
return( vips_image_new_from_file( file->filename,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"page", (int) factor,
|
||||||
|
NULL ) );
|
||||||
|
else
|
||||||
|
return( vips_image_new_from_file( file->filename,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
||||||
/* We support three modes: subifd pyramids, page-based
|
/* We support three modes: subifd pyramids, page-based
|
||||||
* pyramids, and simple multi-page TIFFs (no pyramid).
|
* pyramids, and simple multi-page TIFFs (no pyramid).
|
||||||
@ -1132,7 +1159,6 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) {
|
else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) {
|
||||||
return( vips_image_new_from_file( file->filename,
|
return( vips_image_new_from_file( file->filename,
|
||||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
@ -1325,6 +1351,23 @@ vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"scale", 1.0 / factor,
|
"scale", 1.0 / factor,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
else if( vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ) {
|
||||||
|
/* Optional page-based pyramids.
|
||||||
|
*/
|
||||||
|
if( thumbnail->page_pyramid )
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length,
|
||||||
|
buffer->option_string,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"page", (int) factor,
|
||||||
|
NULL ) );
|
||||||
|
else
|
||||||
|
return( vips_image_new_from_buffer(
|
||||||
|
buffer->buf->data, buffer->buf->length,
|
||||||
|
buffer->option_string,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
||||||
/* We support three modes: subifd pyramids, page-based
|
/* We support three modes: subifd pyramids, page-based
|
||||||
* pyramids, and simple multi-page TIFFs (no pyramid).
|
* pyramids, and simple multi-page TIFFs (no pyramid).
|
||||||
@ -1521,6 +1564,23 @@ vips_thumbnail_source_open( VipsThumbnail *thumbnail, double factor )
|
|||||||
"scale", 1.0 / factor,
|
"scale", 1.0 / factor,
|
||||||
NULL ) );
|
NULL ) );
|
||||||
}
|
}
|
||||||
|
else if( vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ) {
|
||||||
|
/* Optional page-based pyramids.
|
||||||
|
*/
|
||||||
|
if( thumbnail->page_pyramid )
|
||||||
|
return( vips_image_new_from_source(
|
||||||
|
source->source,
|
||||||
|
source->option_string,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
"page", (int) factor,
|
||||||
|
NULL ) );
|
||||||
|
else
|
||||||
|
return( vips_image_new_from_source(
|
||||||
|
source->source,
|
||||||
|
source->option_string,
|
||||||
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
|
NULL ) );
|
||||||
|
}
|
||||||
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) {
|
||||||
/* We support three modes: subifd pyramids, page-based
|
/* We support three modes: subifd pyramids, page-based
|
||||||
* pyramids, and simple multi-page TIFFs (no pyramid).
|
* pyramids, and simple multi-page TIFFs (no pyramid).
|
||||||
|
@ -56,6 +56,7 @@ MOSAIC_MARKS = [[489, 140], [66, 141],
|
|||||||
MOSAIC_VERTICAL_MARKS = [[388, 44], [364, 346],
|
MOSAIC_VERTICAL_MARKS = [[388, 44], [364, 346],
|
||||||
[384, 17], [385, 629],
|
[384, 17], [385, 629],
|
||||||
[527, 42], [503, 959]]
|
[527, 42], [503, 959]]
|
||||||
|
JP2K_FILE = os.path.join(IMAGES, "world.jp2")
|
||||||
|
|
||||||
unsigned_formats = [pyvips.BandFormat.UCHAR,
|
unsigned_formats = [pyvips.BandFormat.UCHAR,
|
||||||
pyvips.BandFormat.USHORT,
|
pyvips.BandFormat.USHORT,
|
||||||
|
BIN
test/test-suite/images/world.jp2
Normal file
BIN
test/test-suite/images/world.jp2
Normal file
Binary file not shown.
@ -17,7 +17,7 @@ from helpers import \
|
|||||||
GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, \
|
GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, \
|
||||||
temp_filename, assert_almost_equal_objects, have, skip_if_no, \
|
temp_filename, assert_almost_equal_objects, have, skip_if_no, \
|
||||||
TIF1_FILE, TIF2_FILE, TIF4_FILE, WEBP_LOOKS_LIKE_SVG_FILE, \
|
TIF1_FILE, TIF2_FILE, TIF4_FILE, WEBP_LOOKS_LIKE_SVG_FILE, \
|
||||||
WEBP_ANIMATED_FILE
|
WEBP_ANIMATED_FILE, JP2K_FILE
|
||||||
|
|
||||||
class TestForeign:
|
class TestForeign:
|
||||||
tempdir = None
|
tempdir = None
|
||||||
@ -1119,6 +1119,54 @@ class TestForeign:
|
|||||||
y = pyvips.Image.new_from_buffer(buf, "")
|
y = pyvips.Image.new_from_buffer(buf, "")
|
||||||
assert y.get("exif-ifd0-Make").split(" ")[0] == "banana"
|
assert y.get("exif-ifd0-Make").split(" ")[0] == "banana"
|
||||||
|
|
||||||
|
@skip_if_no("jp2kload")
|
||||||
|
def test_jp2kload(self):
|
||||||
|
def jp2k_valid(im):
|
||||||
|
a = im(402, 73)
|
||||||
|
assert_almost_equal_objects(a, [141, 144, 73], threshold=2)
|
||||||
|
assert im.width == 800
|
||||||
|
assert im.height == 400
|
||||||
|
assert im.bands == 3
|
||||||
|
|
||||||
|
self.file_loader("jp2kload", JP2K_FILE, jp2k_valid)
|
||||||
|
self.buffer_loader("jp2kload_buffer", JP2K_FILE, jp2k_valid)
|
||||||
|
|
||||||
|
@skip_if_no("jp2ksave")
|
||||||
|
def test_jp2ksave(self):
|
||||||
|
self.save_load_buffer("jp2ksave_buffer", "jp2kload_buffer",
|
||||||
|
self.colour, 80)
|
||||||
|
|
||||||
|
buf = self.colour.jp2ksave_buffer(lossless=True)
|
||||||
|
im2 = pyvips.Image.new_from_buffer(buf, "")
|
||||||
|
assert (self.colour == im2).min() == 255
|
||||||
|
|
||||||
|
# higher Q should mean a bigger buffer
|
||||||
|
b1 = self.mono.jp2ksave_buffer(Q=10)
|
||||||
|
b2 = self.mono.jp2ksave_buffer(Q=90)
|
||||||
|
assert len(b2) > len(b1)
|
||||||
|
|
||||||
|
# disabling chroma subsample should mean a bigger buffer
|
||||||
|
b1 = self.colour.jp2ksave_buffer(subsample_mode="on")
|
||||||
|
b2 = self.colour.jp2ksave_buffer(subsample_mode="off")
|
||||||
|
assert len(b2) > len(b1)
|
||||||
|
|
||||||
|
# enabling lossless should mean a bigger buffer
|
||||||
|
b1 = self.colour.jp2ksave_buffer(lossless=False)
|
||||||
|
b2 = self.colour.jp2ksave_buffer(lossless=True)
|
||||||
|
assert len(b2) > len(b1)
|
||||||
|
|
||||||
|
# 16-bit colour load and save
|
||||||
|
im = self.colour.colourspace("rgb16")
|
||||||
|
buf = im.jp2ksave_buffer(lossless=True)
|
||||||
|
im2 = pyvips.Image.new_from_buffer(buf, "")
|
||||||
|
assert (im == im2).min() == 255
|
||||||
|
|
||||||
|
# openjpeg 32-bit load and save doesn't seem to work, comment out
|
||||||
|
# im = self.colour.colourspace("rgb16").cast("uint") << 14
|
||||||
|
# buf = im.jp2ksave_buffer(lossless=True)
|
||||||
|
# im2 = pyvips.Image.new_from_buffer(buf, "")
|
||||||
|
# assert (im == im2).min() == 255
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pytest.main()
|
pytest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user