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
|
||||
libgif-dev libopenexr-dev libpango1.0-dev
|
||||
libgsf-1-dev libopenslide-dev libffi-dev
|
||||
libopenjp2-7-dev
|
||||
|
||||
- name: Install macOS dependencies
|
||||
if: contains(matrix.os, 'macos')
|
||||
@ -69,6 +70,7 @@ jobs:
|
||||
librsvg libspng libtiff
|
||||
little-cms2 openexr openslide
|
||||
orc pango poppler webp
|
||||
openjpeg
|
||||
|
||||
- name: Install Clang 10
|
||||
env:
|
||||
|
@ -20,6 +20,8 @@
|
||||
- add vips_fitsload_source(), vips_niftiload_source()
|
||||
- png and gif load note background colour as metadata [781545872]
|
||||
- add vips_image_[set|get]_array_double()
|
||||
- add GIF load with libnsgif
|
||||
- add JPEG2000 load and save
|
||||
|
||||
22/12/20 start 8.10.6
|
||||
- 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_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
|
||||
AC_ARG_WITH([heif],
|
||||
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
|
||||
(requires librsvg-2.0 2.34.0 or later)
|
||||
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
|
||||
(requires openslide-3.3.0 or later)
|
||||
Matlab load with matio: $with_matio
|
||||
|
@ -263,12 +263,6 @@ TAB_SIZE = 8
|
||||
|
||||
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
|
||||
# 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
|
||||
|
@ -5,70 +5,72 @@ endif
|
||||
noinst_LTLIBRARIES = libforeign.la
|
||||
|
||||
libforeign_la_SOURCES = \
|
||||
pforeign.h \
|
||||
heifload.c \
|
||||
heifsave.c \
|
||||
niftiload.c \
|
||||
niftisave.c \
|
||||
quantise.c \
|
||||
exif.c \
|
||||
nsgifload.c \
|
||||
analyze2vips.c \
|
||||
analyzeload.c \
|
||||
cairo.c \
|
||||
pdfload.c \
|
||||
pdfiumload.c \
|
||||
svgload.c \
|
||||
radiance.c \
|
||||
radload.c \
|
||||
radsave.c \
|
||||
ppmload.c \
|
||||
ppmsave.c \
|
||||
csvload.c \
|
||||
csvsave.c \
|
||||
matrixload.c \
|
||||
matrixsave.c \
|
||||
dzsave.c \
|
||||
rawload.c \
|
||||
rawsave.c \
|
||||
vipsload.c \
|
||||
vipssave.c \
|
||||
dbh.h \
|
||||
analyzeload.c \
|
||||
analyze2vips.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 \
|
||||
dzsave.c \
|
||||
exif.c \
|
||||
fits.c \
|
||||
fitsload.c \
|
||||
fitssave.c \
|
||||
tiff.h \
|
||||
tiff.c \
|
||||
vips2tiff.c \
|
||||
tiff2vips.c \
|
||||
tiffload.c \
|
||||
tiffsave.c \
|
||||
openslide2vips.c \
|
||||
openslideload.c \
|
||||
webpload.c \
|
||||
webpsave.c \
|
||||
webp2vips.c \
|
||||
vips2webp.c \
|
||||
vips2jpeg.c \
|
||||
foreign.c \
|
||||
heifload.c \
|
||||
heifsave.c \
|
||||
jp2kload.c \
|
||||
jp2ksave.c \
|
||||
jpeg2vips.c \
|
||||
jpeg.h \
|
||||
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
|
||||
|
||||
|
@ -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_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_buffer_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();
|
||||
#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
|
||||
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_source_get_type();
|
||||
#endif /*HAVE_NSGIF*/
|
||||
|
@ -230,7 +230,8 @@ vips_foreign_load_heif_build( VipsObject *object )
|
||||
printf( "vips_foreign_load_heif_build:\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( vips_source_rewind( heif->source ) )
|
||||
if( heif->source &&
|
||||
vips_source_rewind( heif->source ) )
|
||||
return( -1 );
|
||||
|
||||
if( !heif->ctx ) {
|
||||
@ -245,7 +246,6 @@ vips_foreign_load_heif_build( VipsObject *object )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_heif_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
@ -253,7 +253,6 @@ vips_foreign_load_heif_build( VipsObject *object )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
static const char *heif_magic[] = {
|
||||
"ftypheic", /* A regular heif 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 ||
|
||||
( 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,
|
||||
"chroma", chroma );
|
||||
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.
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
void vips__heif_image_print( struct heif_image *img );
|
||||
|
||||
extern const char *vips__jp2k_suffs[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -372,7 +372,7 @@ int vips_openslideload_source( VipsSource *source, VipsImage **out, ... )
|
||||
|
||||
/**
|
||||
* 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_OFF: never perform subsampling
|
||||
*
|
||||
@ -676,6 +676,19 @@ int vips_niftiload_source( VipsSource *source, VipsImage **out, ... )
|
||||
int vips_niftisave( VipsImage *in, const char *filename, ... )
|
||||
__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:
|
||||
* @VIPS_FOREIGN_DZ_LAYOUT_DZ: use DeepZoom directory layout
|
||||
|
@ -136,11 +136,11 @@ typedef struct _VipsThumbnail {
|
||||
int heif_thumbnail_width;
|
||||
int heif_thumbnail_height;
|
||||
|
||||
/* For TIFF sources, open subifds to get pyr layers.
|
||||
/* Pyramids are stored in subifds.
|
||||
*/
|
||||
gboolean subifd_pyramid;
|
||||
|
||||
/* For TIFF sources, open pages to get pyr layers.
|
||||
/* Pyramids are stored in pages.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
static void
|
||||
vips_thumbnail_get_tiff_pyramid_page( VipsThumbnail *thumbnail )
|
||||
vips_thumbnail_get_pyramid_page( VipsThumbnail *thumbnail )
|
||||
{
|
||||
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_thumbnail_get_tiff_pyramid_page:\n" );
|
||||
printf( "vips_thumbnail_get_pyramid_page:\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf( "vips_thumbnail_get_tiff_pyramid_page: "
|
||||
printf( "vips_thumbnail_get_pyramid_page: "
|
||||
"%d layer pyramid detected\n",
|
||||
thumbnail->n_pages );
|
||||
#endif /*DEBUG*/
|
||||
@ -500,7 +500,7 @@ vips_thumbnail_find_jpegshrink( VipsThumbnail *thumbnail,
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Find the best pyramid (openslide or tiff) level.
|
||||
/* Find the best pyramid (openslide, tiff, etc.) level.
|
||||
*/
|
||||
static int
|
||||
vips_thumbnail_find_pyrlevel( VipsThumbnail *thumbnail,
|
||||
@ -553,7 +553,21 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
||||
thumbnail->subifd_pyramid = FALSE;
|
||||
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 )
|
||||
thumbnail->page_pyramid = FALSE;
|
||||
@ -576,8 +590,9 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
||||
factor = vips_thumbnail_find_jpegshrink( thumbnail,
|
||||
thumbnail->input_width, thumbnail->input_height );
|
||||
else if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ||
|
||||
vips_isprefix( "VipsForeignLoadJp2k", thumbnail->loader ) ||
|
||||
vips_isprefix( "VipsForeignLoadOpenslide",
|
||||
thumbnail->loader ) ) {
|
||||
thumbnail->loader ) ) {
|
||||
if( thumbnail->level_count > 0 )
|
||||
factor = vips_thumbnail_find_pyrlevel( thumbnail,
|
||||
thumbnail->input_width,
|
||||
@ -1112,7 +1127,19 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor )
|
||||
"scale", 1.0 / factor,
|
||||
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 ) ) {
|
||||
/* We support three modes: subifd pyramids, page-based
|
||||
* pyramids, and simple multi-page TIFFs (no pyramid).
|
||||
@ -1132,7 +1159,6 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor )
|
||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||
NULL ) );
|
||||
}
|
||||
|
||||
else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) {
|
||||
return( vips_image_new_from_file( file->filename,
|
||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||
@ -1325,6 +1351,23 @@ vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, double factor )
|
||||
"scale", 1.0 / factor,
|
||||
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 ) ) {
|
||||
/* We support three modes: subifd pyramids, page-based
|
||||
* pyramids, and simple multi-page TIFFs (no pyramid).
|
||||
@ -1521,6 +1564,23 @@ vips_thumbnail_source_open( VipsThumbnail *thumbnail, double factor )
|
||||
"scale", 1.0 / factor,
|
||||
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 ) ) {
|
||||
/* We support three modes: subifd pyramids, page-based
|
||||
* 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],
|
||||
[384, 17], [385, 629],
|
||||
[527, 42], [503, 959]]
|
||||
JP2K_FILE = os.path.join(IMAGES, "world.jp2")
|
||||
|
||||
unsigned_formats = [pyvips.BandFormat.UCHAR,
|
||||
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, \
|
||||
temp_filename, assert_almost_equal_objects, have, skip_if_no, \
|
||||
TIF1_FILE, TIF2_FILE, TIF4_FILE, WEBP_LOOKS_LIKE_SVG_FILE, \
|
||||
WEBP_ANIMATED_FILE
|
||||
WEBP_ANIMATED_FILE, JP2K_FILE
|
||||
|
||||
class TestForeign:
|
||||
tempdir = None
|
||||
@ -1119,6 +1119,54 @@ class TestForeign:
|
||||
y = pyvips.Image.new_from_buffer(buf, "")
|
||||
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__':
|
||||
pytest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user