Merge branch 'master' into add-libnsgif
This commit is contained in:
commit
f74d6c795d
@ -24,12 +24,15 @@
|
||||
22/12/20 start 8.10.6
|
||||
- don't seek on bad file descriptors [kleisauke]
|
||||
- check for null memory sources [kleisauke]
|
||||
- revise ppmload, fixing a couple of small bugs
|
||||
- signal error on EOF in jpegload more reliably [bozaro]
|
||||
- better error detection in spngload [randy408]
|
||||
- improve ppmload, fixing a couple of small bugs
|
||||
- improve EOF detection in jpegload [bozaro]
|
||||
- improve error detection in spngload [randy408]
|
||||
- fix includes of glib headers in C++ [lovell]
|
||||
- fix build with more modern librsvg [lovell]
|
||||
- fix a possible segv with very wide images [f1ac]
|
||||
- fix issue thumbnailing RGBA images in linear mode [jjonesrs]
|
||||
- improve vipsthumbnail profile handling
|
||||
- fix tiff deflate predictor setting [Adios]
|
||||
|
||||
18/12/20 started 8.10.5
|
||||
- fix potential /0 in animated webp load [lovell]
|
||||
|
542
configure.ac
542
configure.ac
@ -26,7 +26,12 @@ VIPS_MAJOR_VERSION=vips_major_version()
|
||||
VIPS_MINOR_VERSION=vips_minor_version()
|
||||
VIPS_MICRO_VERSION=vips_micro_version()
|
||||
VIPS_VERSION=vips_version()
|
||||
VIPS_VERSION_STRING=$VIPS_VERSION-`date -u -r $srcdir/ChangeLog`
|
||||
VIPS_VERSION_STRING="$VIPS_VERSION-$(date -u -r $srcdir/ChangeLog)"
|
||||
|
||||
# packages add to these as we find them
|
||||
VIPS_CFLAGS=""
|
||||
VIPS_INCLUDES=""
|
||||
VIPS_LIBS=""
|
||||
|
||||
# libtool library versioning ... not user-visible (except as part of the
|
||||
# library file name) and does not correspond to major/minor/micro above
|
||||
@ -74,31 +79,31 @@ done
|
||||
# add headers that form the public vips8 API .. don't do a find and exclude,
|
||||
# we end up excluding almost everything argh
|
||||
headers="\
|
||||
basic.h \
|
||||
vips.h \
|
||||
object.h \
|
||||
image.h \
|
||||
error.h \
|
||||
foreign.h \
|
||||
freqfilt.h \
|
||||
interpolate.h \
|
||||
header.h \
|
||||
histogram.h \
|
||||
operation.h \
|
||||
enumtypes.h \
|
||||
conversion.h \
|
||||
arithmetic.h \
|
||||
colour.h \
|
||||
convolution.h \
|
||||
create.h \
|
||||
draw.h \
|
||||
morphology.h \
|
||||
mosaicing.h \
|
||||
type.h \
|
||||
rect.h \
|
||||
resample.h \
|
||||
memory.h \
|
||||
region.h"
|
||||
basic.h \
|
||||
vips.h \
|
||||
object.h \
|
||||
image.h \
|
||||
error.h \
|
||||
foreign.h \
|
||||
freqfilt.h \
|
||||
interpolate.h \
|
||||
header.h \
|
||||
histogram.h \
|
||||
operation.h \
|
||||
enumtypes.h \
|
||||
conversion.h \
|
||||
arithmetic.h \
|
||||
colour.h \
|
||||
convolution.h \
|
||||
create.h \
|
||||
draw.h \
|
||||
morphology.h \
|
||||
mosaicing.h \
|
||||
type.h \
|
||||
rect.h \
|
||||
resample.h \
|
||||
memory.h \
|
||||
region.h"
|
||||
|
||||
for name in $headers; do
|
||||
vips_introspection_sources="$vips_introspection_sources include/vips/$name"
|
||||
@ -141,69 +146,35 @@ AM_CONDITIONAL(ENABLE_DEPRECATED, [test x"$enable_deprecated" = x"yes"])
|
||||
# this gets pasted into version.h as a #define
|
||||
AC_SUBST(VIPS_ENABLE_DEPRECATED)
|
||||
|
||||
AC_MSG_CHECKING([for native Win32])
|
||||
case "$host" in
|
||||
*-*-mingw*)
|
||||
vips_os_win32=yes
|
||||
;;
|
||||
*)
|
||||
vips_os_win32=no
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$vips_os_win32])
|
||||
|
||||
if test x"$vips_os_win32" = x"yes"; then
|
||||
AC_DEFINE(OS_WIN32,1,[native win32])
|
||||
|
||||
# makes gcc use win native alignment
|
||||
VIPS_CFLAGS="-mms-bitfields $VIPS_CFLAGS"
|
||||
fi
|
||||
|
||||
# CImg needs flags changed on win32
|
||||
AM_CONDITIONAL(OS_WIN32, [test x"$vips_os_win32" = x"yes"])
|
||||
|
||||
# Cygwin/mingw need binary open to avoid CR/LF madness
|
||||
# ... should be a better way to test for this
|
||||
AC_MSG_CHECKING([for binary open needed])
|
||||
AC_MSG_CHECKING([for -mms-bitfields support])
|
||||
case "$host_os" in
|
||||
cygwin* | mingw*)
|
||||
vips_binary_open=yes
|
||||
mingw*)
|
||||
# makes gcc use win native alignment
|
||||
# GCC >= 4.7 and Clang >= 11 does this automatically, see:
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1510#note_841637
|
||||
VIPS_CFLAGS="-mms-bitfields $VIPS_CFLAGS"
|
||||
AC_MSG_RESULT([yes])
|
||||
;;
|
||||
*)
|
||||
vips_binary_open=no
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$vips_binary_open])
|
||||
if test x"$vips_binary_open" = x"yes"; then
|
||||
AC_DEFINE(BINARY_OPEN,1,[define to open non-text files in binary mode])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for Mac OS X])
|
||||
case "$host" in
|
||||
*-*-darwin*)
|
||||
vips_os_darwin=yes
|
||||
;;
|
||||
*)
|
||||
vips_os_darwin=no
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$vips_os_darwin])
|
||||
|
||||
if test x"$vips_os_darwin" = x"yes"; then
|
||||
AC_DEFINE(VIPS_OS_DARWIN,1,[native Mac OS X])
|
||||
fi
|
||||
|
||||
# set the default directory for ICC profiles
|
||||
if test x"$vips_os_darwin" = x"yes"; then
|
||||
profile_dir="/Library/ColorSync/Profiles"
|
||||
elif test x"$vips_os_win32" = x"yes"; then
|
||||
# need double escapes since this will get pasted into a #define in a C
|
||||
# header ... the C:\Windows is usually overrwritten with the result of
|
||||
# GetWindowsDirectoryW()
|
||||
profile_dir="C:\\\\Windows\\\\System32\\\\spool\\\\drivers\\\\color"
|
||||
else
|
||||
profile_dir="/usr/share/color/icc"
|
||||
fi
|
||||
case "$host_os" in
|
||||
darwin*)
|
||||
profile_dir="/Library/ColorSync/Profiles"
|
||||
;;
|
||||
mingw*)
|
||||
# need double escapes since this will get pasted into a #define in a C
|
||||
# header ... the C:\Windows is usually overwritten with the result of
|
||||
# GetWindowsDirectoryW()
|
||||
profile_dir="C:\\\\Windows\\\\System32\\\\spool\\\\drivers\\\\color"
|
||||
;;
|
||||
*)
|
||||
profile_dir="/usr/share/color/icc"
|
||||
;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(VIPS_ICC_DIR,"$profile_dir",[default directory for ICC profiles])
|
||||
|
||||
# we want largefile support, if possible
|
||||
@ -435,20 +406,23 @@ PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0"
|
||||
# from 2.62 we have datetime
|
||||
PKG_CHECK_MODULES(DATE_TIME_FORMAT_ISO8601, glib-2.0 >= 2.62,
|
||||
[AC_DEFINE(HAVE_DATE_TIME_FORMAT_ISO8601,1,
|
||||
[define if your glib has g_date_time_format_iso8601().]
|
||||
[define if your glib has g_date_time_format_iso8601().]
|
||||
)
|
||||
],
|
||||
[:
|
||||
]
|
||||
)
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $GIO_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $GIO_LIBS"
|
||||
|
||||
# if available, we use pthread_setattr_default_np() to raise the per-thread
|
||||
# stack size ... musl (libc on Alpine), for example, has a very small stack per
|
||||
# thread by default
|
||||
save_pthread_LIBS="$LIBS"
|
||||
save_pthread_CFLAGS="$CFLAGS"
|
||||
LIBS="$LIBS $GTHREAD_LIBS"
|
||||
CFLAGS="$CFLAGS $GTHREAD_CFLAGS"
|
||||
LIBS="$LIBS $REQUIRED_LIBS"
|
||||
CFLAGS="$CFLAGS $REQUIRED_CFLAGS"
|
||||
AC_CHECK_FUNC(pthread_setattr_default_np,
|
||||
[AC_DEFINE(HAVE_PTHREAD_DEFAULT_NP,1,[have pthread_setattr_default_np().])
|
||||
]
|
||||
@ -456,11 +430,6 @@ AC_CHECK_FUNC(pthread_setattr_default_np,
|
||||
LIBS="$save_pthread_LIBS"
|
||||
CFLAGS="$save_pthread_CFLAGS"
|
||||
|
||||
if test x"$vips_os_win32" = x"yes"; then
|
||||
AC_DEFINE(HAVE_G_WIN32_GET_COMMAND_LINE,1,[define if your glib has g_win32_get_command_line().])
|
||||
have_g_win32_get_command_line=yes
|
||||
fi
|
||||
|
||||
# from 2.48 we have g_uint_checked_mul() etc.
|
||||
PKG_CHECK_MODULES(HAVE_CHECKED_MUL, glib-2.0 >= 2.48,
|
||||
[AC_DEFINE(HAVE_CHECKED_MUL,1,[define if your glib has checked multiply.])
|
||||
@ -486,6 +455,9 @@ if test x"$expat_found" = x"no"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $EXPAT_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $EXPAT_LIBS"
|
||||
|
||||
# optional supporting libraries
|
||||
|
||||
AC_ARG_WITH([gsf],
|
||||
@ -510,13 +482,16 @@ if test x"$with_gsf" != x"no"; then
|
||||
PKG_CHECK_MODULES(GSF_ZIP64, libgsf-1 >= 1.14.31,
|
||||
[AC_DEFINE(HAVE_GSF_ZIP64,1,[define if your libgsf supports zip64.])
|
||||
AC_DEFINE(HAVE_GSF_DEFLATE_LEVEL,1,
|
||||
[define if your libgsf supports deflate-level.])
|
||||
[define if your libgsf supports deflate-level.])
|
||||
],
|
||||
[:
|
||||
]
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $GSF_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $GSF_LIBS"
|
||||
|
||||
AC_ARG_WITH([fftw],
|
||||
AS_HELP_STRING([--without-fftw], [build without fftw (default: test)]))
|
||||
|
||||
@ -532,6 +507,9 @@ if test x"$with_fftw" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $FFTW_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $FFTW_LIBS"
|
||||
|
||||
# ImageMagick
|
||||
AC_ARG_WITH([magick],
|
||||
AS_HELP_STRING([--without-magick], [build without libMagic (default: test)]))
|
||||
@ -595,7 +573,7 @@ if test x"$magick6" = x"yes"; then
|
||||
CFLAGS="$CFLAGS $MAGICK_CFLAGS"
|
||||
AC_CHECK_MEMBER([struct _ImageInfo.number_scenes],
|
||||
AC_DEFINE(HAVE_NUMBER_SCENES,1,
|
||||
[define if your magick has ImageInfo.number_scenes.]),
|
||||
[define if your magick has ImageInfo.number_scenes.]),
|
||||
[],
|
||||
[#include <magick/api.h>])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
@ -653,11 +631,11 @@ fi
|
||||
# save but not load, for example
|
||||
AC_ARG_ENABLE([magickload],
|
||||
AS_HELP_STRING([--disable-magickload],
|
||||
[disable libMagic load (default: enabled)]))
|
||||
[disable libMagic load (default: enabled)]))
|
||||
|
||||
AC_ARG_ENABLE([magicksave],
|
||||
AS_HELP_STRING([--disable-magicksave],
|
||||
[disable libMagic save (default: enabled)]))
|
||||
[disable libMagic save (default: enabled)]))
|
||||
|
||||
if test x"$enable_magicksave" != x"yes"; then
|
||||
# we need ImportImagePixels ... GM is missing this sadly
|
||||
@ -665,12 +643,12 @@ if test x"$enable_magicksave" != x"yes"; then
|
||||
LIBS="$LIBS $MAGICK_LIBS"
|
||||
AC_CHECK_FUNCS(ImportImagePixels,[
|
||||
AC_DEFINE(HAVE_IMPORTIMAGEPIXELS,1,
|
||||
[define if you have ImportImagePixels.])
|
||||
[define if you have ImportImagePixels.])
|
||||
],[]
|
||||
)
|
||||
AC_CHECK_FUNCS(ImagesToBlob,[
|
||||
AC_DEFINE(HAVE_IMAGESTOBLOB,1,
|
||||
[define if you have ImagesToBlob.])
|
||||
[define if you have ImagesToBlob.])
|
||||
],[]
|
||||
)
|
||||
LIBS="$save_LIBS"
|
||||
@ -691,6 +669,9 @@ else
|
||||
enable_magicksave=no
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $MAGICK_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $MAGICK_LIBS"
|
||||
|
||||
# orc
|
||||
AC_ARG_WITH([orc],
|
||||
AS_HELP_STRING([--without-orc], [build without orc (default: test)]))
|
||||
@ -705,7 +686,7 @@ if test x"$with_orc" != x"no"; then
|
||||
LIBS="$LIBS $ORC_LIBS"
|
||||
AC_CHECK_FUNCS(orc_program_get_error,
|
||||
AC_DEFINE(HAVE_ORC_PROGRAM_GET_ERROR,1,
|
||||
[define if your orc has orc_program_get_error.]))
|
||||
[define if your orc has orc_program_get_error.]))
|
||||
LIBS="$save_LIBS"
|
||||
],
|
||||
[AC_MSG_WARN([orc-0.4.11 or later not found; disabling orc support])
|
||||
@ -719,7 +700,7 @@ fi
|
||||
if test x"$with_orc" = x"yes"; then
|
||||
PKG_CHECK_MODULES(ORC_CF_PROTECTION, orc-0.4 >= 0.4.31,
|
||||
[AC_DEFINE(HAVE_ORC_CF_PROTECTION,1,
|
||||
[define if your orc works with cf-protection.]
|
||||
[define if your orc works with cf-protection.]
|
||||
)
|
||||
],
|
||||
[:
|
||||
@ -727,6 +708,9 @@ if test x"$with_orc" = x"yes"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $ORC_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $ORC_LIBS"
|
||||
|
||||
# lcms ... refuse to use lcms1
|
||||
AC_ARG_WITH([lcms],
|
||||
AS_HELP_STRING([--without-lcms], [build without lcms (default: test)]))
|
||||
@ -747,6 +731,9 @@ fi
|
||||
# is detected
|
||||
AM_CONDITIONAL(ENABLE_LCMS, [test x"$with_lcms" != x"no"])
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $LCMS_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $LCMS_LIBS"
|
||||
|
||||
# OpenEXR
|
||||
AC_ARG_WITH([OpenEXR],
|
||||
AS_HELP_STRING([--without-OpenEXR], [build without OpenEXR (default: test)]))
|
||||
@ -764,6 +751,9 @@ if test x"$with_OpenEXR" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $OPENEXR_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $OPENEXR_LIBS"
|
||||
|
||||
# nifti
|
||||
AC_ARG_WITH([nifti],
|
||||
AS_HELP_STRING([--without-nifti], [build without nifti (default: test)]))
|
||||
@ -777,6 +767,10 @@ if test x"$with_nifti" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $NIFTI_CFLAGS"
|
||||
VIPS_INCLUDES="$VIPS_INCLUDES $NIFTI_INCLUDES"
|
||||
VIPS_LIBS="$VIPS_LIBS $NIFTI_LIBS"
|
||||
|
||||
# libheif
|
||||
AC_ARG_WITH([heif],
|
||||
AS_HELP_STRING([--without-heif], [build without libheif (default: test)]))
|
||||
@ -790,13 +784,13 @@ if test x"$with_heif" != x"no"; then
|
||||
# this variable
|
||||
if test x"$have_h265_decoder" != x"no" -o x"$have_avif_decoder" = x"yes"; then
|
||||
AC_DEFINE(HAVE_HEIF_DECODER,1,
|
||||
[define if your libheif has decode support.])
|
||||
[define if your libheif has decode support.])
|
||||
fi
|
||||
have_h265_encoder=`$PKG_CONFIG libheif --variable builtin_h265_encoder`
|
||||
have_avif_encoder=`$PKG_CONFIG libheif --variable builtin_avif_encoder`
|
||||
if test x"$have_h265_encoder" != x"no" -o x"$have_avif_encoder" = x"yes"; then
|
||||
AC_DEFINE(HAVE_HEIF_ENCODER,1,
|
||||
[define if your libheif has encode support.])
|
||||
[define if your libheif has encode support.])
|
||||
fi
|
||||
PACKAGES_USED="$PACKAGES_USED libheif"
|
||||
],
|
||||
@ -817,7 +811,7 @@ if test x"$with_heif" = x"yes"; then
|
||||
LIBS="$LIBS $HEIF_LIBS"
|
||||
AC_CHECK_FUNCS(heif_image_handle_get_raw_color_profile,[
|
||||
AC_DEFINE(HAVE_HEIF_COLOR_PROFILE,1,
|
||||
[define if you have heif_image_handle_get_raw_color_profile.])
|
||||
[define if you have heif_image_handle_get_raw_color_profile.])
|
||||
],[]
|
||||
)
|
||||
LIBS="$save_LIBS"
|
||||
@ -838,12 +832,15 @@ if test x"$with_heif" = x"yes"; then
|
||||
CFLAGS="$CFLAGS $HEIF_CFLAGS"
|
||||
AC_CHECK_MEMBER([struct heif_decoding_options.convert_hdr_to_8bit],[
|
||||
AC_DEFINE(HAVE_HEIF_DECODING_OPTIONS_CONVERT_HDR_TO_8BIT,1,
|
||||
[define if you have heif_decoding_options.convert_hdr_to_8bit])
|
||||
[define if you have heif_decoding_options.convert_hdr_to_8bit])
|
||||
],[],
|
||||
[#include <libheif/heif.h>])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $HEIF_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $HEIF_LIBS"
|
||||
|
||||
# pdfium
|
||||
AC_ARG_WITH([pdfium],
|
||||
AS_HELP_STRING([--without-pdfium], [build without pdfium (default: test)]))
|
||||
@ -864,6 +861,9 @@ if test x"$with_pdfium" != x"no"; then
|
||||
])
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $PDFIUM_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $PDFIUM_LIBS"
|
||||
|
||||
# poppler
|
||||
AC_ARG_WITH([poppler],
|
||||
AS_HELP_STRING([--without-poppler], [build without poppler (default: test)]))
|
||||
@ -879,6 +879,9 @@ if test x"$with_poppler" != x"no"; then
|
||||
])
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $POPPLER_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $POPPLER_LIBS"
|
||||
|
||||
# librsvg
|
||||
AC_ARG_WITH([rsvg],
|
||||
AS_HELP_STRING([--without-rsvg], [build without rsvg (default: test)]))
|
||||
@ -895,6 +898,9 @@ if test x"$with_rsvg" != x"no"; then
|
||||
])
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $RSVG_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $RSVG_LIBS"
|
||||
|
||||
# zlib
|
||||
# some platforms, like macosx, are missing the .pc files for zlib, so
|
||||
# we fall back to FIND_ZLIB
|
||||
@ -918,6 +924,10 @@ if test x"$with_zlib" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $ZLIB_CFLAGS"
|
||||
VIPS_INCLUDES="$VIPS_INCLUDES $ZLIB_INCLUDES"
|
||||
VIPS_LIBS="$VIPS_LIBS $ZLIB_LIBS"
|
||||
|
||||
# OpenSlide
|
||||
AC_ARG_WITH([openslide],
|
||||
AS_HELP_STRING([--without-openslide],
|
||||
@ -945,6 +955,9 @@ if test x"$with_openslide" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $OPENSLIDE_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $OPENSLIDE_LIBS"
|
||||
|
||||
# matio
|
||||
AC_ARG_WITH([matio],
|
||||
AS_HELP_STRING([--without-matio], [build without matio (default: test)]))
|
||||
@ -961,6 +974,9 @@ if test x"$with_matio" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $MATIO_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $MATIO_LIBS"
|
||||
|
||||
# not external libraries, but have options to disable them, helps to
|
||||
# reduce attack surface
|
||||
|
||||
@ -1014,6 +1030,9 @@ if test x"$with_cfitsio" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $CFITSIO_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $CFITSIO_LIBS"
|
||||
|
||||
# libwebp ... target 0.6+ to reduce complication
|
||||
# webp has the stuff for handling metadata in two separate libraries -- we
|
||||
# insit on having all of them
|
||||
@ -1032,6 +1051,9 @@ if test x"$with_libwebp" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $LIBWEBP_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $LIBWEBP_LIBS"
|
||||
|
||||
# pangoft2
|
||||
AC_ARG_WITH([pangoft2],
|
||||
AS_HELP_STRING([--without-pangoft2],
|
||||
@ -1049,6 +1071,9 @@ if test x"$with_pangoft2" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $PANGOFT2_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $PANGOFT2_LIBS"
|
||||
|
||||
# look for TIFF with pkg-config ... fall back to our tester
|
||||
# pkgconfig support for libtiff starts with libtiff-4
|
||||
AC_ARG_WITH([tiff],
|
||||
@ -1070,7 +1095,7 @@ if test x"$with_tiff" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
# WEBP in TIFF added in libtiff 4.0.10
|
||||
# ZSTD and WEBP in TIFF added in libtiff 4.0.10
|
||||
if test x"$with_tiff" != x"no"; then
|
||||
save_INCLUDES="$INCLUDES"
|
||||
INCLUDES="$INCLUDES $TIFF_INCLUDES"
|
||||
@ -1084,6 +1109,10 @@ if test x"$with_tiff" != x"no"; then
|
||||
INCLUDES="$save_INCLUDES"
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $TIFF_CFLAGS"
|
||||
VIPS_INCLUDES="$VIPS_INCLUDES $TIFF_INCLUDES"
|
||||
VIPS_LIBS="$VIPS_LIBS $TIFF_LIBS"
|
||||
|
||||
# Look for libspng first
|
||||
# 0.6.1 uses "libspng.pc", git master libspng uses "spng.pc"
|
||||
AC_ARG_WITH([libspng],
|
||||
@ -1107,6 +1136,9 @@ if test x"$with_libspng" != x"no"; then
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $SPNG_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $SPNG_LIBS"
|
||||
|
||||
# look for PNG with pkg-config ... fall back to our tester
|
||||
# we can have both PNG and SPNG enabled, with SPNG for read and PNG for
|
||||
# write
|
||||
@ -1137,11 +1169,15 @@ if test x"$with_png" != x"no"; then
|
||||
CFLAGS="$PNG_INCLUDES $CFLAGS"
|
||||
AC_CHECK_FUNCS(png_set_chunk_malloc_max,
|
||||
AC_DEFINE(HAVE_PNG_SET_CHUNK_MALLOC_MAX,1,
|
||||
[define if your libpng has png_set_chunk_malloc_max.]))
|
||||
[define if your libpng has png_set_chunk_malloc_max.]))
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $PNG_CFLAGS"
|
||||
VIPS_INCLUDES="$VIPS_INCLUDES $PNG_INCLUDES"
|
||||
VIPS_LIBS="$VIPS_LIBS $PNG_LIBS"
|
||||
|
||||
# look for libimagequant with pkg-config (only if libpng is enabled)
|
||||
AC_ARG_WITH([imagequant],
|
||||
AS_HELP_STRING([--without-imagequant], [build without imagequant (default: test)]))
|
||||
@ -1160,6 +1196,9 @@ else
|
||||
with_imagequant=no
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $IMAGEQUANT_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $IMAGEQUANT_LIBS"
|
||||
|
||||
# look for libjpeg with pkg-config ... fall back to our tester
|
||||
AC_ARG_WITH([jpeg],
|
||||
AS_HELP_STRING([--without-jpeg], [build without libjpeg (default: test)]))
|
||||
@ -1192,11 +1231,15 @@ if test x"$with_jpeg" != x"no"; then
|
||||
CFLAGS="$JPEG_INCLUDES $CFLAGS"
|
||||
AC_CHECK_FUNCS(jpeg_c_bool_param_supported,
|
||||
AC_DEFINE(HAVE_JPEG_EXT_PARAMS,1,
|
||||
[define if your libjpeg has extension parameters.]))
|
||||
[define if your libjpeg has extension parameters.]))
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $JPEG_CFLAGS"
|
||||
VIPS_INCLUDES="$VIPS_INCLUDES $JPEG_INCLUDES"
|
||||
VIPS_LIBS="$VIPS_LIBS $JPEG_LIBS"
|
||||
|
||||
# libexif
|
||||
AC_ARG_WITH([libexif],
|
||||
AS_HELP_STRING([--without-libexif], [build without libexif (default: test)]))
|
||||
@ -1224,6 +1267,9 @@ if test x"$with_libexif" != x"no"; then
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $EXIF_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $EXIF_LIBS"
|
||||
|
||||
# fuzzing
|
||||
AC_ARG_VAR([LIB_FUZZING_ENGINE],
|
||||
[fuzzing library, e.g. /path/to/libFuzzer.a])
|
||||
@ -1231,71 +1277,47 @@ if test x"$LIB_FUZZING_ENGINE" = x; then
|
||||
LIB_FUZZING_ENGINE="libstandaloneengine.a"
|
||||
fi
|
||||
|
||||
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS \
|
||||
$GTHREAD_CFLAGS \
|
||||
$GIO_CFLAGS \
|
||||
$REQUIRED_CFLAGS \
|
||||
$EXPAT_CFLAGS \
|
||||
$ZLIB_CFLAGS \
|
||||
$PANGOFT2_CFLAGS \
|
||||
$GSF_CFLAGS \
|
||||
$FFTW_CFLAGS \
|
||||
$MAGICK_CFLAGS \
|
||||
$JPEG_CFLAGS \
|
||||
$SPNG_CFLAGS \
|
||||
$PNG_CFLAGS \
|
||||
$IMAGEQUANT_CFLAGS \
|
||||
$EXIF_CFLAGS \
|
||||
$MATIO_CFLAGS \
|
||||
$CFITSIO_CFLAGS \
|
||||
$LIBWEBP_CFLAGS \
|
||||
$LIBWEBPMUX_CFLAGS \
|
||||
$RSVG_CFLAGS \
|
||||
$PDFIUM_CFLAGS \
|
||||
$POPPLER_CFLAGS \
|
||||
$OPENEXR_CFLAGS \
|
||||
$OPENSLIDE_CFLAGS \
|
||||
$ORC_CFLAGS \
|
||||
$TIFF_CFLAGS \
|
||||
$LCMS_CFLAGS \
|
||||
$HEIF_CFLAGS"
|
||||
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
|
||||
|
||||
VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES $NIFTI_INCLUDES"
|
||||
VIPS_LIBS="$ZLIB_LIBS \
|
||||
$HEIF_LIBS \
|
||||
$MAGICK_LIBS \
|
||||
$SPNG_LIBS \
|
||||
$PNG_LIBS \
|
||||
$IMAGEQUANT_LIBS \
|
||||
$TIFF_LIBS \
|
||||
$JPEG_LIBS \
|
||||
$GTHREAD_LIBS \
|
||||
$GIO_LIBS \
|
||||
$REQUIRED_LIBS \
|
||||
$EXPAT_LIBS \
|
||||
$PANGOFT2_LIBS \
|
||||
$GSF_LIBS \
|
||||
$FFTW_LIBS \
|
||||
$ORC_LIBS \
|
||||
$LCMS_LIBS \
|
||||
$RSVG_LIBS \
|
||||
$NIFTI_LIBS \
|
||||
$PDFIUM_LIBS \
|
||||
$POPPLER_LIBS \
|
||||
$OPENEXR_LIBS \
|
||||
$OPENSLIDE_LIBS \
|
||||
$CFITSIO_LIBS \
|
||||
$LIBWEBP_LIBS \
|
||||
$LIBWEBPMUX_LIBS \
|
||||
$MATIO_LIBS \
|
||||
$EXIF_LIBS \
|
||||
-lm"
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $VIPS_DEBUG_FLAGS $REQUIRED_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $REQUIRED_LIBS -lm"
|
||||
|
||||
# autoconf hates multi-line AC_SUBST so we have to have another copy of this
|
||||
# thing
|
||||
VIPS_CONFIG="native win32: $vips_os_win32, native OS X: $vips_os_darwin, open files in binary mode: $vips_binary_open, enable debug: $enable_debug, enable deprecated library components: $enable_deprecated, enable docs with gtkdoc: $enable_gtk_doc, gobject introspection: $found_introspection, enable radiance support: $with_radiance, enable analyze support: $with_analyze, enable PPM load/save: $with_ppm, enable GIF load: $with_nsgif, generate C++ docs: $with_doxygen, use fftw3 for FFT: $with_fftw, Magick package: $with_magickpackage, Magick API version: $magick_version, load with libMagick: $enable_magickload, save with libMagick: $enable_magicksave, accelerate loops with orc: $with_orc, ICC profile support with lcms: $with_lcms, NIfTI load/save with niftiio: $with_nifti, HEIC/AVIF load/save with libheif: $with_heif, EXR load/save with OpenEXR: $with_OpenEXR, slide load with OpenSlide: $with_openslide, Matlab load with matio: $with_matio, PDF load with PDFium: $with_pdfium, PDF load with poppler-glib: $with_poppler, SVG load with librsvg-2.0: $with_rsvg, zlib: $with_zlib, FITS load with cfitsio: $with_cfitsio, WebP load/save with libwebp: $with_libwebp, text rendering with pangoft2: $with_pangoft2, PNG load with libspng: $with_libspng, PNG load/save with libpng: $with_png, support 8bpp PNG quantisation: $with_imagequant, TIFF load/save with libtiff: $with_tiff, JPEG load/save with libjpeg: $with_jpeg, image pyramid export: $with_gsf, use libexif to load/save JPEG metadata: $with_libexif"
|
||||
VIPS_CONFIG="\
|
||||
enable debug: $enable_debug, \
|
||||
enable deprecated library components: $enable_deprecated, \
|
||||
enable docs with gtkdoc: $enable_gtk_doc, \
|
||||
gobject introspection: $found_introspection, \
|
||||
RAD load/save: $with_radiance, \
|
||||
Analyze7 load/save: $with_analyze, \
|
||||
PPM load/save: $with_ppm, \
|
||||
GIF load: $with_nsgif, \
|
||||
generate C++ docs: $with_doxygen, \
|
||||
use fftw3 for FFT: $with_fftw, \
|
||||
accelerate loops with orc: $with_orc, \
|
||||
ICC profile support with lcms: $with_lcms, \
|
||||
zlib: $with_zlib, \
|
||||
text rendering with pangoft2: $with_pangoft2, \
|
||||
EXIF metadata support with libexif: $with_libexif, \
|
||||
JPEG load/save with libjpeg: $with_jpeg, \
|
||||
PNG load with libspng: $with_libspng, \
|
||||
PNG load/save with libpng: $with_png, \
|
||||
8bpp PNG quantisation: $with_imagequant, \
|
||||
TIFF load/save with libtiff: $with_tiff, \
|
||||
image pyramid save: $with_gsf, \
|
||||
HEIC/AVIF load/save with libheif: $with_heif, \
|
||||
WebP load/save with libwebp: $with_libwebp, \
|
||||
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, \
|
||||
Matlab load with matio: $with_matio, \
|
||||
NIfTI load/save with niftiio: $with_nifti, \
|
||||
FITS load/save with cfitsio: $with_cfitsio, \
|
||||
Magick package: $with_magickpackage, \
|
||||
Magick API version: $magick_version, \
|
||||
load with libMagickCore: $enable_magickload, \
|
||||
save with libMagickCore: $enable_magicksave"
|
||||
|
||||
AC_SUBST(VIPS_LIBDIR)
|
||||
|
||||
@ -1312,109 +1334,99 @@ TOP_SRCDIR=$ac_pwd
|
||||
AC_SUBST(TOP_SRCDIR)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
vips.pc
|
||||
vips-cpp.pc
|
||||
Makefile
|
||||
$srcdir/libvips/include/vips/version.h
|
||||
libvips/include/Makefile
|
||||
libvips/include/vips/Makefile
|
||||
libvips/Makefile
|
||||
libvips/arithmetic/Makefile
|
||||
libvips/colour/Makefile
|
||||
libvips/colour/profiles/Makefile
|
||||
libvips/conversion/Makefile
|
||||
libvips/convolution/Makefile
|
||||
libvips/deprecated/Makefile
|
||||
libvips/foreign/Makefile
|
||||
libvips/foreign/libnsgif/Makefile
|
||||
libvips/freqfilt/Makefile
|
||||
libvips/histogram/Makefile
|
||||
libvips/draw/Makefile
|
||||
libvips/iofuncs/Makefile
|
||||
libvips/morphology/Makefile
|
||||
libvips/mosaicing/Makefile
|
||||
libvips/create/Makefile
|
||||
libvips/resample/Makefile
|
||||
cplusplus/Doxyfile
|
||||
cplusplus/include/Makefile
|
||||
cplusplus/include/vips/Makefile
|
||||
cplusplus/Makefile
|
||||
tools/Makefile
|
||||
tools/batch_crop
|
||||
tools/batch_image_convert
|
||||
tools/batch_rubber_sheet
|
||||
tools/light_correct
|
||||
tools/shrink_width
|
||||
test/Makefile
|
||||
test/variables.sh
|
||||
test/test-suite/Makefile
|
||||
test/test-suite/helpers/Makefile
|
||||
man/Makefile
|
||||
doc/Makefile
|
||||
doc/libvips-docs.xml
|
||||
po/Makefile.in
|
||||
fuzz/Makefile
|
||||
vips.pc
|
||||
vips-cpp.pc
|
||||
Makefile
|
||||
$srcdir/libvips/include/vips/version.h
|
||||
libvips/include/Makefile
|
||||
libvips/include/vips/Makefile
|
||||
libvips/Makefile
|
||||
libvips/arithmetic/Makefile
|
||||
libvips/colour/Makefile
|
||||
libvips/colour/profiles/Makefile
|
||||
libvips/conversion/Makefile
|
||||
libvips/convolution/Makefile
|
||||
libvips/deprecated/Makefile
|
||||
libvips/foreign/Makefile
|
||||
libvips/freqfilt/Makefile
|
||||
libvips/histogram/Makefile
|
||||
libvips/draw/Makefile
|
||||
libvips/iofuncs/Makefile
|
||||
libvips/morphology/Makefile
|
||||
libvips/mosaicing/Makefile
|
||||
libvips/create/Makefile
|
||||
libvips/resample/Makefile
|
||||
cplusplus/Doxyfile
|
||||
cplusplus/include/Makefile
|
||||
cplusplus/include/vips/Makefile
|
||||
cplusplus/Makefile
|
||||
tools/Makefile
|
||||
tools/batch_crop
|
||||
tools/batch_image_convert
|
||||
tools/batch_rubber_sheet
|
||||
tools/light_correct
|
||||
tools/shrink_width
|
||||
test/Makefile
|
||||
test/variables.sh
|
||||
test/test-suite/Makefile
|
||||
test/test-suite/helpers/Makefile
|
||||
man/Makefile
|
||||
doc/Makefile
|
||||
doc/libvips-docs.xml
|
||||
po/Makefile.in
|
||||
fuzz/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
# also add any new items to VIPS_CONFIG above
|
||||
AC_MSG_RESULT([dnl
|
||||
* build options
|
||||
native win32: $vips_os_win32
|
||||
native OS X: $vips_os_darwin
|
||||
open files in binary mode: $vips_binary_open
|
||||
enable debug: $enable_debug
|
||||
enable deprecated library components: $enable_deprecated
|
||||
enable docs with gtkdoc: $enable_gtk_doc
|
||||
gobject introspection: $found_introspection
|
||||
enable radiance load/save: $with_radiance
|
||||
enable analyze load/save: $with_analyze
|
||||
enable PPM load/save: $with_ppm
|
||||
enable GIF load: $with_nsgif
|
||||
## Build options
|
||||
enable debug: $enable_debug
|
||||
enable deprecated library components: $enable_deprecated
|
||||
enable docs with gtkdoc: $enable_gtk_doc
|
||||
gobject introspection: $found_introspection
|
||||
RAD load/save: $with_radiance
|
||||
Analyze7 load/save: $with_analyze
|
||||
PPM load/save: $with_ppm
|
||||
GIF load: $with_nsgif
|
||||
generate C++ docs: $with_doxygen
|
||||
|
||||
* optional dependencies
|
||||
use fftw3 for FFT: $with_fftw
|
||||
Magick package: $with_magickpackage
|
||||
Magick API version: $magick_version
|
||||
load with libMagick: $enable_magickload
|
||||
save with libMagick: $enable_magicksave
|
||||
accelerate loops with orc: $with_orc
|
||||
(requires orc-0.4.11 or later)
|
||||
ICC profile support with lcms: $with_lcms
|
||||
NIfTI load/save with niftiio: $with_nifti
|
||||
HEIC/AVIF load/save with libheif: $with_heif
|
||||
EXR load/save with OpenEXR: $with_OpenEXR
|
||||
slide load with OpenSlide: $with_openslide
|
||||
(requires openslide-3.3.0 or later)
|
||||
Matlab load with matio: $with_matio
|
||||
PDF load with PDFium: $with_pdfium
|
||||
PDF load with poppler-glib: $with_poppler
|
||||
(requires poppler-glib 0.16.0 or later)
|
||||
SVG load with librsvg-2.0: $with_rsvg
|
||||
(requires librsvg-2.0 2.34.0 or later)
|
||||
zlib: $with_zlib
|
||||
FITS load/save with cfitsio: $with_cfitsio
|
||||
WebP load/save with libwebp: $with_libwebp
|
||||
(requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later)
|
||||
text rendering with pangoft2: $with_pangoft2
|
||||
PNG load with libspng: $with_libspng
|
||||
(requires libspng-0.6 or later)
|
||||
PNG load/save with libpng: $with_png
|
||||
(requires libpng-1.2.9 or later)
|
||||
support 8bpp PNG quantisation: $with_imagequant
|
||||
(requires libimagequant)
|
||||
TIFF load/save with libtiff: $with_tiff
|
||||
JPEG load/save with libjpeg: $with_jpeg
|
||||
image pyramid export: $with_gsf
|
||||
(requires libgsf-1 1.14.26 or later)
|
||||
use libexif to load/save JPEG metadata: $with_libexif
|
||||
])
|
||||
## Optional dependencies
|
||||
use fftw3 for FFT: $with_fftw
|
||||
accelerate loops with orc: $with_orc
|
||||
(requires orc-0.4.11 or later)
|
||||
ICC profile support with lcms: $with_lcms
|
||||
zlib: $with_zlib
|
||||
text rendering with pangoft2: $with_pangoft2
|
||||
EXIF metadata support with libexif: $with_libexif
|
||||
|
||||
if test x"$vips_os_win32" = x"yes"; then
|
||||
if test x"$have_g_win32_get_command_line" != x"yes"; then
|
||||
AC_MSG_RESULT([dnl
|
||||
Your glib is too old, vips will not support unicode command-line arguments.
|
||||
])
|
||||
fi
|
||||
fi
|
||||
## File format support
|
||||
JPEG load/save with libjpeg: $with_jpeg
|
||||
PNG load with libspng: $with_libspng
|
||||
(requires libspng-0.6 or later)
|
||||
PNG load/save with libpng: $with_png
|
||||
(requires libpng-1.2.9 or later)
|
||||
8bpp PNG quantisation: $with_imagequant
|
||||
(requires libimagequant)
|
||||
TIFF load/save with libtiff: $with_tiff
|
||||
image pyramid save: $with_gsf
|
||||
(requires libgsf-1 1.14.26 or later)
|
||||
HEIC/AVIF load/save with libheif: $with_heif
|
||||
WebP load/save with libwebp: $with_libwebp
|
||||
(requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later)
|
||||
PDF load with PDFium: $with_pdfium
|
||||
PDF load with poppler-glib: $with_poppler
|
||||
(requires poppler-glib 0.16.0 or later)
|
||||
SVG load with librsvg-2.0: $with_rsvg
|
||||
(requires librsvg-2.0 2.34.0 or later)
|
||||
EXR load with OpenEXR: $with_OpenEXR
|
||||
slide load with OpenSlide: $with_openslide
|
||||
(requires openslide-3.3.0 or later)
|
||||
Matlab load with matio: $with_matio
|
||||
NIfTI load/save with niftiio: $with_nifti
|
||||
FITS load/save with cfitsio: $with_cfitsio
|
||||
Magick package: $with_magickpackage
|
||||
Magick API version: $magick_version
|
||||
load with libMagickCore: $enable_magickload
|
||||
save with libMagickCore: $enable_magicksave
|
||||
])
|
||||
|
@ -127,7 +127,7 @@ HTML_IMAGES = \
|
||||
# we have some files in markdown ... convert to docbook for gtk-doc
|
||||
# pandoc makes section headers, we want refsect3 for gtk-doc
|
||||
.md.xml:
|
||||
pandoc -s --template="$(realpath pandoc-docbook-template.docbook)" --wrap=none -V title="$<" -f markdown+smart -t docbook-smart -o $@ $<
|
||||
pandoc -s --template="$(realpath pandoc-docbook-template.docbook)" --wrap=none -V title="$<" -f markdown+smart -t docbook -o $@ $<
|
||||
sed -e s/section/refsect3/g < $@ > x && mv x $@
|
||||
|
||||
# Our markdown source files
|
||||
|
@ -19,10 +19,35 @@
|
||||
<refsect3 xml:id="dont-bind-the-top-level-c-api">
|
||||
<title>Don’t bind the top-level C API</title>
|
||||
<para>
|
||||
The libvips C API (vips_add() and so on) is very inconvenient and dangerous to use from other languages due to its heavy use of varargs.
|
||||
The libvips C API (vips_add() and so on) was designed to be easy for humans to write. It is inconvenient and dangerous to use from other languages due to its heavy use of varargs.
|
||||
</para>
|
||||
<para>
|
||||
It’s much better to use the layer below. This lower layer is structured as create operator, set parameters, execute, extract results. For example, you can execute vips_invert() like this:
|
||||
It’s much better to use the layer below. This lower layer is structured as:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Create operator. You can use vips_operation_new() to make a new <literal>VipsOperation</literal> object from an operator nickname, like <literal>"add"</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Set parameters. You can loop over the operation with vips_argument_map() to get the name and type of each input argument. For each argument, you need to get the value from your language, convert to a <literal>GValue</literal>, then use g_object_set_property() to set that value on the operator.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute with vips_cache_operation_build().
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Extract results. Again, you loop over the operator arguments with vips_argument_map(), but instead of inputs, this time you look for output arguments. You extract their value with g_object_get_property(), and pass the value back to your language.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
For example, you can execute vips_invert() like this:
|
||||
</para>
|
||||
<programlisting language="c">
|
||||
/* compile with
|
||||
@ -111,17 +136,11 @@ main( int argc, char **argv )
|
||||
return( 0 );
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
libvips has a couple of extra things to let you examine the arguments and types of an operator at runtime. Use vips_argument_map() to loop over all the arguments of an operator, and vips_object_get_argument() to fetch the type and flags of a specific argument.
|
||||
</para>
|
||||
<para>
|
||||
Use vips_operation_get_flags() to get general information about an operator.
|
||||
</para>
|
||||
</refsect3>
|
||||
<refsect3 xml:id="compiled-language-which-can-call-c">
|
||||
<title>Compiled language which can call C</title>
|
||||
<para>
|
||||
The C++ binding uses this lower layer to define a function called <literal>VImage::call()</literal> which can call any libvips operator with a not-varargs set of variable arguments.
|
||||
The C++ binding uses this lower layer to define a function called <literal>VImage::call()</literal> which can call any libvips operator with a set of variable arguments.
|
||||
</para>
|
||||
<para>
|
||||
A small Python program walks the set of all libvips operators and generates a set of static bindings. For example:
|
||||
@ -139,7 +158,7 @@ VImage VImage::invert( VOption *options )
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
So from C++ you can call any libvips operator (though without type-safety) with <literal>VImage::call()</literal>, or use the member functions on <literal>VImage</literal> to get type-safe calls for at least the required operator arguments.
|
||||
So from C++ you can call any libvips operator (though without static typechecking) with <literal>VImage::call()</literal>, or use the member functions on <literal>VImage</literal> to get type-checked calls for at least the required operator arguments.
|
||||
</para>
|
||||
<para>
|
||||
The <literal>VImage</literal> class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features.
|
||||
@ -151,13 +170,13 @@ VImage VImage::invert( VOption *options )
|
||||
Languages like Ruby, Python, JavaScript and LuaJIT can’t call C directly, but they do support FFI. The bindings for these languages work rather like C++, but use FFI to call into libvips and run operations.
|
||||
</para>
|
||||
<para>
|
||||
Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by the <literal>Image</literal> class as libvips operators. This makes these bindings self-writing: they only contain a small amount of code and just expose everything they find in the libvips class hierarchy.
|
||||
Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by the <literal>Image</literal> class as libvips operators. In effect, the binding is generated at runtime.
|
||||
</para>
|
||||
</refsect3>
|
||||
<refsect3 xml:id="dynamic-langauge-without-ffi">
|
||||
<title>Dynamic langauge without FFI</title>
|
||||
<para>
|
||||
PHP does not have FFI, unfortunately, so for this language a small native module implements the general <literal>vips_call()</literal> function for PHP language types, and a larger pure PHP layer makes it convenient to use.
|
||||
PHP does not have a useful FFI, unfortunately, so for this language a small C module implements the general <literal>vips_call()</literal> function for PHP language types, and a larger pure PHP layer makes it convenient to use.
|
||||
</para>
|
||||
</refsect3>
|
||||
<refsect3 xml:id="gobject-introspection">
|
||||
|
@ -67,7 +67,7 @@ typedef struct _VipsFlatten {
|
||||
*/
|
||||
VipsArrayDouble *background;
|
||||
|
||||
/* The [double] converted to the input image format.
|
||||
/* The [double] background converted to the input image format.
|
||||
*/
|
||||
VipsPel *ink;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
* - max_alpha defaults to 65535 for RGB16/GREY16
|
||||
* 24/11/17 lovell
|
||||
* - match normalised alpha to output type
|
||||
* 27/2/21 jjonesrs
|
||||
* - revise range clipping and 1/x, again
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -70,7 +72,8 @@ typedef VipsConversionClass VipsUnpremultiplyClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
||||
|
||||
/* Unpremultiply an N-band image.
|
||||
/* Unpremultiply an N-band image. Don't use clip_alpha to calculate factor: we
|
||||
* want over and undershoots on alpha and RGB to cancel.
|
||||
*/
|
||||
#define UNPRE_MANY( IN, OUT ) { \
|
||||
IN * restrict p = (IN *) in; \
|
||||
@ -78,18 +81,11 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
||||
\
|
||||
for( x = 0; x < width; x++ ) { \
|
||||
IN alpha = p[alpha_band]; \
|
||||
OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \
|
||||
\
|
||||
if( alpha != 0 ) { \
|
||||
OUT factor = max_alpha / alpha; \
|
||||
\
|
||||
for( i = 0; i < alpha_band; i++ ) \
|
||||
q[i] = factor * p[i]; \
|
||||
q[alpha_band] = alpha; \
|
||||
} \
|
||||
else \
|
||||
for( i = 0; i < alpha_band + 1; i++ ) \
|
||||
q[i] = 0; \
|
||||
\
|
||||
for( i = 0; i < alpha_band; i++ ) \
|
||||
q[i] = factor * p[i]; \
|
||||
q[alpha_band] = VIPS_CLIP( 0, alpha, max_alpha ); \
|
||||
for( i = alpha_band + 1; i < bands; i++ ) \
|
||||
q[i] = p[i]; \
|
||||
\
|
||||
@ -106,21 +102,12 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
||||
\
|
||||
for( x = 0; x < width; x++ ) { \
|
||||
IN alpha = p[3]; \
|
||||
OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \
|
||||
\
|
||||
if( alpha != 0 ) { \
|
||||
OUT factor = max_alpha / alpha; \
|
||||
\
|
||||
q[0] = factor * p[0]; \
|
||||
q[1] = factor * p[1]; \
|
||||
q[2] = factor * p[2]; \
|
||||
q[3] = alpha; \
|
||||
} \
|
||||
else { \
|
||||
q[0] = 0; \
|
||||
q[1] = 0; \
|
||||
q[2] = 0; \
|
||||
q[3] = 0; \
|
||||
} \
|
||||
q[0] = factor * p[0]; \
|
||||
q[1] = factor * p[1]; \
|
||||
q[2] = factor * p[2]; \
|
||||
q[3] = VIPS_CLIP( 0, alpha, max_alpha ); \
|
||||
\
|
||||
p += 4; \
|
||||
q += 4; \
|
||||
|
@ -104,7 +104,7 @@ vips__tiff_openout( const char *path, gboolean bigtiff )
|
||||
|
||||
/* Need the utf-16 version on Windows.
|
||||
*/
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
GError *error = NULL;
|
||||
wchar_t *path16;
|
||||
@ -119,9 +119,9 @@ vips__tiff_openout( const char *path, gboolean bigtiff )
|
||||
|
||||
g_free( path16 );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
tif = TIFFOpen( path, mode );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
if( !tif ) {
|
||||
vips_error( "tiff",
|
||||
|
@ -590,8 +590,8 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
|
||||
* User @level to set the ZSTD compression level. Use @lossless to
|
||||
* set WEBP lossless mode on. Use @Q to set the WEBP compression level.
|
||||
*
|
||||
* Use @predictor to set the predictor for lzw and deflate compression. It
|
||||
* defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal
|
||||
* Use @predictor to set the predictor for lzw, deflate and zstd compression.
|
||||
* It defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal
|
||||
* differencing. Please refer to the libtiff
|
||||
* specifications for further discussion of various predictors.
|
||||
*
|
||||
|
@ -333,9 +333,9 @@ struct _Wtiff {
|
||||
VipsPel *tbuf; /* TIFF output buffer */
|
||||
int tls; /* Tile line size */
|
||||
|
||||
int compression; /* Compression type */
|
||||
int compression; /* libtiff compression type */
|
||||
int Q; /* JPEG q-factor, webp level */
|
||||
int predictor; /* Predictor value */
|
||||
int predictor; /* libtiff predictor type */
|
||||
int tile; /* Tile or not */
|
||||
int tilew, tileh; /* Tile size */
|
||||
int pyramid; /* Wtiff pyramid */
|
||||
@ -659,12 +659,16 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer )
|
||||
TIFFSetField( tif, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
||||
TIFFSetField( tif, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
||||
}
|
||||
if( wtiff->compression == COMPRESSION_ZSTD )
|
||||
if( wtiff->compression == COMPRESSION_ZSTD ) {
|
||||
TIFFSetField( tif, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
||||
if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||
TIFFSetField( tif,
|
||||
TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||
}
|
||||
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
||||
|
||||
if( (wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE ||
|
||||
wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_LZW) &&
|
||||
if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE ||
|
||||
wtiff->compression == COMPRESSION_LZW) &&
|
||||
wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||
TIFFSetField( tif, TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||
|
||||
@ -1862,10 +1866,19 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
|
||||
TIFFSetField( out, TIFFTAG_WEBP_LEVEL, wtiff->Q );
|
||||
TIFFSetField( out, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
|
||||
}
|
||||
if( wtiff->compression == COMPRESSION_ZSTD )
|
||||
if( wtiff->compression == COMPRESSION_ZSTD ) {
|
||||
TIFFSetField( out, TIFFTAG_ZSTD_LEVEL, wtiff->level );
|
||||
if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||
TIFFSetField( out,
|
||||
TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||
}
|
||||
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
|
||||
|
||||
if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE ||
|
||||
wtiff->compression == COMPRESSION_LZW) &&
|
||||
wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE )
|
||||
TIFFSetField( out, TIFFTAG_PREDICTOR, wtiff->predictor );
|
||||
|
||||
/* We can't copy profiles or xmp :( Set again from wtiff.
|
||||
*/
|
||||
if( !wtiff->strip )
|
||||
|
@ -365,7 +365,6 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name );
|
||||
VIPS_ARGUMENT_COLLECT_END
|
||||
|
||||
*/
|
||||
#if GLIB_CHECK_VERSION( 2, 24, 0 )
|
||||
#define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \
|
||||
if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \
|
||||
GValue value = { 0, }; \
|
||||
@ -383,25 +382,6 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name );
|
||||
VIPS_DEBUG_MSG( "VIPS_OBJECT_COLLECT_SET: err\n" ); \
|
||||
g_free( error ); \
|
||||
}
|
||||
#else
|
||||
#define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \
|
||||
if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \
|
||||
GValue value = { 0, }; \
|
||||
gchar *error = NULL; \
|
||||
\
|
||||
/* Input args are given inline, eg. ("factor", 12.0) \
|
||||
* and must be collected. \
|
||||
*/ \
|
||||
g_value_init( &value, G_PARAM_SPEC_VALUE_TYPE( PSPEC ) ); \
|
||||
G_VALUE_COLLECT( &value, AP, 0, &error ); \
|
||||
\
|
||||
/* Don't bother with the error message. \
|
||||
*/ \
|
||||
if( error ) { \
|
||||
VIPS_DEBUG_MSG( "VIPS_OBJECT_COLLECT_SET: err\n" ); \
|
||||
g_free( error ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VIPS_ARGUMENT_COLLECT_GET( PSPEC, ARG_CLASS, AP ) \
|
||||
g_value_unset( &value ); \
|
||||
|
@ -65,10 +65,10 @@
|
||||
#include <vips/thread.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#include <lmerr.h>
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/**
|
||||
* SECTION: errors
|
||||
@ -294,7 +294,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap )
|
||||
{
|
||||
vips_verror( domain, fmt, ap );
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
char *buf;
|
||||
|
||||
@ -310,7 +310,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap )
|
||||
LocalFree( buf );
|
||||
}
|
||||
}
|
||||
#else /*OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
{
|
||||
char *buf;
|
||||
|
||||
@ -318,7 +318,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap )
|
||||
vips_error( _( "unix error" ), "%s", buf );
|
||||
g_free( buf );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1676,14 +1676,7 @@ vips_image_temp_name( char *name, int size )
|
||||
{
|
||||
static int global_serial = 0;
|
||||
|
||||
/* Old glibs named this differently.
|
||||
*/
|
||||
int serial =
|
||||
#if GLIB_CHECK_VERSION( 2, 30, 0 )
|
||||
g_atomic_int_add( &global_serial, 1 );
|
||||
#else
|
||||
g_atomic_int_exchange_and_add( &global_serial, 1 );
|
||||
#endif
|
||||
int serial = g_atomic_int_add( &global_serial, 1 );
|
||||
|
||||
vips_snprintf( name, size, "temp-%d", serial );
|
||||
}
|
||||
|
@ -290,24 +290,6 @@ empty_log_handler( const gchar *log_domain, GLogLevelFlags log_level,
|
||||
{
|
||||
}
|
||||
|
||||
#if !GLIB_CHECK_VERSION( 2, 31, 0 )
|
||||
static void
|
||||
default_log_handler( const gchar *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *message, gpointer user_data )
|
||||
{
|
||||
if( log_level & (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO) ) {
|
||||
const char *domains = g_getenv( "G_MESSAGES_DEBUG" );
|
||||
|
||||
if( !domains ||
|
||||
(!g_str_equal( domains, "all" ) &&
|
||||
!g_strrstr( domains, log_domain )) )
|
||||
return;
|
||||
}
|
||||
|
||||
g_log_default_handler( log_domain, log_level, message, user_data );
|
||||
}
|
||||
#endif /*!GLIB_CHECK_VERSION( 2, 31, 0 )*/
|
||||
|
||||
/* Attempt to set a minimum stacksize. This can be important on systems with a
|
||||
* very low default, like musl.
|
||||
*/
|
||||
@ -407,7 +389,7 @@ vips_init( const char *argv0 )
|
||||
return( 0 );
|
||||
started = TRUE;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
/* Windows has a limit of 512 files open at once for the fopen() family
|
||||
* of functions, and 2048 for the _open() family. This raises the limit
|
||||
* of fopen() to the same level as _open().
|
||||
@ -415,7 +397,7 @@ vips_init( const char *argv0 )
|
||||
* It will not go any higher than this, unfortunately.
|
||||
*/
|
||||
(void) _setmaxstdio( 2048 );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
vips__threadpool_init();
|
||||
vips__buffer_init();
|
||||
@ -595,18 +577,6 @@ vips_init( const char *argv0 )
|
||||
g_log_set_handler( G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
empty_log_handler, NULL );
|
||||
|
||||
#if !GLIB_CHECK_VERSION( 2, 31, 0 )
|
||||
/* Older glibs can sometimes show G_LOG_LEVEL_{INFO,DEBUG} messages.
|
||||
* Block them ourselves. We test the env var inside the handler since
|
||||
* vips_verbose() can be toggled at runtime.
|
||||
*
|
||||
* Again, we should not call g_log_set_handler(), but this is the only
|
||||
* convenient way to fix this behaviour.
|
||||
*/
|
||||
g_log_set_handler( G_LOG_DOMAIN, G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG,
|
||||
default_log_handler, NULL );
|
||||
#endif /*!GLIB_CHECK_VERSION( 2, 31, 0 )*/
|
||||
|
||||
/* Set a minimum stacksize, if we can.
|
||||
*/
|
||||
if( (vips_min_stack_size = g_getenv( "VIPS_MIN_STACK_SIZE" )) )
|
||||
@ -1057,7 +1027,7 @@ find_file( const char *name )
|
||||
printf( "vips_guess_prefix: g_getenv( \"PATH\" ) == \"%s\"\n", path );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
char *dir;
|
||||
|
||||
@ -1068,9 +1038,9 @@ find_file( const char *name )
|
||||
"%s" G_SEARCHPATH_SEPARATOR_S "%s", dir, path );
|
||||
g_free( dir );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
vips_strncpy( full_path, path, VIPS_PATH_MAX );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
if( (prefix = scan_path( full_path, name )) )
|
||||
return( prefix );
|
||||
@ -1177,9 +1147,9 @@ vips_guess_prefix( const char *argv0, const char *env_name )
|
||||
return( prefix );
|
||||
}
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
prefix = vips__windows_prefix();
|
||||
#else
|
||||
#else /*!G_OS_WIN32*/
|
||||
{
|
||||
char *basename;
|
||||
|
||||
@ -1187,7 +1157,7 @@ vips_guess_prefix( const char *argv0, const char *env_name )
|
||||
prefix = guess_prefix( argv0, basename );
|
||||
g_free( basename );
|
||||
}
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
g_setenv( env_name, prefix, TRUE );
|
||||
|
||||
|
@ -77,18 +77,16 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /*HAVE_UNISTD_H*/
|
||||
#ifdef OS_WIN32
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (!!(m & _S_IFREG))
|
||||
#endif
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (!!(m & _S_IFREG))
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* Does this fd support mmap. Pipes won't, for example.
|
||||
*/
|
||||
@ -99,7 +97,7 @@ vips__mmap_supported( int fd )
|
||||
size_t length = 4096;
|
||||
off_t offset = 0;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
HANDLE hFile = (HANDLE) _get_osfhandle( fd );
|
||||
|
||||
@ -128,7 +126,7 @@ vips__mmap_supported( int fd )
|
||||
CloseHandle( hMMFile );
|
||||
UnmapViewOfFile( baseaddr );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
{
|
||||
int prot = PROT_READ;
|
||||
int flags = MAP_SHARED;
|
||||
@ -138,7 +136,7 @@ vips__mmap_supported( int fd )
|
||||
return( FALSE );
|
||||
munmap( baseaddr, length );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
@ -153,7 +151,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset )
|
||||
length, offset );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
HANDLE hFile = (HANDLE) _get_osfhandle( fd );
|
||||
|
||||
@ -203,7 +201,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset )
|
||||
*/
|
||||
CloseHandle( hMMFile );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
{
|
||||
int prot;
|
||||
int flags;
|
||||
@ -237,7 +235,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset )
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( baseaddr );
|
||||
}
|
||||
@ -245,19 +243,19 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset )
|
||||
int
|
||||
vips__munmap( const void *start, size_t length )
|
||||
{
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
if( !UnmapViewOfFile( (void *) start ) ) {
|
||||
vips_error_system( GetLastError(), "vips_mapfile",
|
||||
"%s", _( "unable to UnmapViewOfFile" ) );
|
||||
return( -1 );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( munmap( (void *) start, length ) < 0 ) {
|
||||
vips_error_system( errno, "vips_mapfile",
|
||||
"%s", _( "unable to munmap file" ) );
|
||||
return( -1 );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -345,7 +343,7 @@ vips_remapfilerw( VipsImage *image )
|
||||
printf( "vips_remapfilerw:\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
HANDLE hFile = (HANDLE) _get_osfhandle( image->fd );
|
||||
HANDLE hMMFile;
|
||||
@ -377,7 +375,7 @@ vips_remapfilerw( VipsImage *image )
|
||||
*/
|
||||
CloseHandle( hMMFile );
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
{
|
||||
assert( image->dtype == VIPS_IMAGE_MMAPIN );
|
||||
|
||||
@ -390,7 +388,7 @@ vips_remapfilerw( VipsImage *image )
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
image->dtype = VIPS_IMAGE_MMAPINRW;
|
||||
|
||||
|
@ -65,23 +65,24 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef OS_WIN32
|
||||
#include <io.h>
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* Try to make an O_BINARY ... sometimes need the leading '_'.
|
||||
*/
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#endif /*_O_BINARY*/
|
||||
#endif /*!O_BINARY*/
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
/* If we have O_BINARY, add it to a mode flags set.
|
||||
*/
|
||||
@ -307,12 +308,12 @@ vips_source_build( VipsObject *object )
|
||||
connection->descriptor = dup( connection->descriptor );
|
||||
connection->close_descriptor = connection->descriptor;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
/* Windows will create eg. stdin and stdout in text mode.
|
||||
* We always read in binary mode.
|
||||
*/
|
||||
_setmode( connection->descriptor, _O_BINARY );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
}
|
||||
|
||||
if( vips_object_argument_isset( object, "blob" ) ) {
|
||||
|
@ -55,23 +55,24 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef OS_WIN32
|
||||
#include <io.h>
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* Try to make an O_BINARY ... sometimes need the leading '_'.
|
||||
*/
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#endif /*_O_BINARY*/
|
||||
#endif /*!O_BINARY*/
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
/* If we have O_BINARY, add it to a mode flags set.
|
||||
*/
|
||||
@ -143,12 +144,12 @@ vips_target_build( VipsObject *object )
|
||||
connection->descriptor = dup( connection->descriptor );
|
||||
connection->close_descriptor = connection->descriptor;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
/* Windows will create eg. stdin and stdout in text mode.
|
||||
* We always write in binary mode.
|
||||
*/
|
||||
_setmode( connection->descriptor, _O_BINARY );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
}
|
||||
else if( target->memory )
|
||||
target->memory_buffer = g_byte_array_new();
|
||||
|
@ -75,9 +75,9 @@
|
||||
#include <vips/thread.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/**
|
||||
* SECTION: threadpool
|
||||
@ -338,7 +338,7 @@ get_num_processors( void )
|
||||
|
||||
#endif /*G_OS_UNIX*/
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
/* Count the CPUs currently available to this process.
|
||||
*/
|
||||
@ -365,7 +365,7 @@ get_num_processors( void )
|
||||
nproc = af_count;
|
||||
}
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( nproc );
|
||||
#endif /*!GLIB_CHECK_VERSION( 2, 48, 1 )*/
|
||||
|
@ -53,27 +53,27 @@
|
||||
#endif /*HAVE_IO_H*/
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif /*OS_WIN32*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/debug.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* Temp buffer for snprintf() layer on old systems.
|
||||
*/
|
||||
#define MAX_BUF (100000)
|
||||
|
||||
/* Try to make an O_BINARY ... sometimes need the leading '_'.
|
||||
*/
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#endif /*_O_BINARY*/
|
||||
#endif /*!O_BINARY*/
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
/* If we have O_BINARY, add it to a mode flags set.
|
||||
*/
|
||||
@ -562,15 +562,15 @@ vips_filename_suffix_match( const char *path, const char *suffixes[] )
|
||||
gint64
|
||||
vips_file_length( int fd )
|
||||
{
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
struct _stati64 st;
|
||||
|
||||
if( _fstati64( fd, &st ) == -1 ) {
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
struct stat st;
|
||||
|
||||
if( fstat( fd, &st ) == -1 ) {
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
vips_error_system( errno, "vips_file_length",
|
||||
"%s", _( "unable to get file stats" ) );
|
||||
return( -1 );
|
||||
@ -600,7 +600,7 @@ vips__write( int fd, const void *buf, size_t count )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
/* Set the create date on a file. On Windows, the create date may be copied
|
||||
* over from an existing file of the same name, unless you reset it.
|
||||
*
|
||||
@ -619,7 +619,7 @@ vips__set_create_time( int fd )
|
||||
SystemTimeToFileTime( &st, &ft );
|
||||
SetFileTime( handle, &ft, &ft, &ft );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* open() with a utf8 filename, setting errno.
|
||||
*/
|
||||
@ -638,10 +638,10 @@ vips__open( const char *filename, int flags, int mode )
|
||||
|
||||
fd = g_open( filename, flags, mode );
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
if( mode & O_CREAT )
|
||||
vips__set_create_time( fd );
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( fd );
|
||||
}
|
||||
@ -661,10 +661,10 @@ vips__fopen( const char *filename, const char *mode )
|
||||
|
||||
fp = g_fopen( filename, mode );
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
if( mode[0] == 'w' )
|
||||
vips__set_create_time( _fileno( fp ) );
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( fp );
|
||||
}
|
||||
@ -698,14 +698,14 @@ vips__file_open_read( const char *filename, const char *fallback_dir,
|
||||
char *mode;
|
||||
FILE *fp;
|
||||
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
if( text_mode )
|
||||
mode = "r";
|
||||
else
|
||||
mode = "rb";
|
||||
#else /*BINARY_OPEN*/
|
||||
#else /*!G_PLATFORM_WIN32*/
|
||||
mode = "r";
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
if( (fp = vips__fopen( filename, mode )) )
|
||||
return( fp );
|
||||
@ -734,14 +734,14 @@ vips__file_open_write( const char *filename, gboolean text_mode )
|
||||
char *mode;
|
||||
FILE *fp;
|
||||
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
if( text_mode )
|
||||
mode = "w";
|
||||
else
|
||||
mode = "wb";
|
||||
#else /*BINARY_OPEN*/
|
||||
#else /*!G_PLATFORM_WIN32*/
|
||||
mode = "w";
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
if( !(fp = vips__fopen( filename, mode )) ) {
|
||||
vips_error_system( errno, "vips__file_open_write",
|
||||
@ -1089,15 +1089,15 @@ vips__seek_no_error( int fd, gint64 pos, int whence )
|
||||
{
|
||||
gint64 new_pos;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
new_pos = _lseeki64( fd, pos, whence );
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
/* On error, eg. opening a directory and seeking to the end, lseek()
|
||||
* on linux seems to return 9223372036854775807 ((1 << 63) - 1)
|
||||
* rather than (off_t) -1 for reasons I don't understand.
|
||||
*/
|
||||
new_pos = lseek( fd, pos, whence );
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( new_pos );
|
||||
}
|
||||
@ -1128,7 +1128,7 @@ vips__seek( int fd, gint64 pos, int whence )
|
||||
int
|
||||
vips__ftruncate( int fd, gint64 pos )
|
||||
{
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
HANDLE hFile = (HANDLE) _get_osfhandle( fd );
|
||||
|
||||
@ -1140,13 +1140,13 @@ vips__ftruncate( int fd, gint64 pos )
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( ftruncate( fd, pos ) ) {
|
||||
vips_error_system( errno, "vips__ftruncate",
|
||||
"%s", _( "unable to truncate" ) );
|
||||
return( -1 );
|
||||
}
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -1620,7 +1620,7 @@ vips__temp_dir( void )
|
||||
const char *tmpd;
|
||||
|
||||
if( !(tmpd = g_getenv( "TMPDIR" )) ) {
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
static gboolean done = FALSE;
|
||||
static char buf[256];
|
||||
|
||||
@ -1629,9 +1629,9 @@ vips__temp_dir( void )
|
||||
strcpy( buf, "C:\\temp" );
|
||||
}
|
||||
tmpd = buf;
|
||||
#else /*!OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
tmpd = "/tmp";
|
||||
#endif /*!OS_WIN32*/
|
||||
#endif /*!G_OS_WIN32*/
|
||||
}
|
||||
|
||||
return( tmpd );
|
||||
@ -1651,14 +1651,7 @@ vips__temp_name( const char *format )
|
||||
char file2[FILENAME_MAX];
|
||||
char *name;
|
||||
|
||||
/* Old glibs named this differently.
|
||||
*/
|
||||
int serial =
|
||||
#if GLIB_CHECK_VERSION( 2, 30, 0 )
|
||||
g_atomic_int_add( &global_serial, 1 );
|
||||
#else
|
||||
g_atomic_int_exchange_and_add( &global_serial, 1 );
|
||||
#endif
|
||||
int serial = g_atomic_int_add( &global_serial, 1 );
|
||||
|
||||
vips_snprintf( file, FILENAME_MAX, "vips-%d-%u",
|
||||
serial, g_random_int() );
|
||||
@ -1961,7 +1954,7 @@ vips__random_add( guint32 seed, int value )
|
||||
static void *
|
||||
vips_icc_dir_once( void *null )
|
||||
{
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
/* From glib get_windows_directory_root()
|
||||
*/
|
||||
wchar_t wwindowsdir[MAX_PATH];
|
||||
@ -1983,7 +1976,7 @@ vips_icc_dir_once( void *null )
|
||||
return( (void *) full_path );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( (void *) VIPS_ICC_DIR );
|
||||
}
|
||||
@ -1997,7 +1990,7 @@ vips__icc_dir( void )
|
||||
vips_icc_dir_once, NULL ) );
|
||||
}
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
static HMODULE vips__dll = NULL;
|
||||
#ifdef DLL_EXPORT
|
||||
BOOL WINAPI
|
||||
@ -2009,19 +2002,19 @@ DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
return( TRUE );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
static void *
|
||||
vips__windows_prefix_once( void *null )
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
prefix = g_win32_get_package_installation_directory_of_module(
|
||||
vips__dll );
|
||||
#else
|
||||
#else /*!G_OS_WIN32*/
|
||||
prefix = (char *) g_getenv( "VIPSHOME" );
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
return( (void *) prefix );
|
||||
}
|
||||
|
@ -115,13 +115,13 @@
|
||||
|
||||
/* Try to make an O_BINARY ... sometimes need the leading '_'.
|
||||
*/
|
||||
#ifdef BINARY_OPEN
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#endif /*_O_BINARY*/
|
||||
#endif /*!O_BINARY*/
|
||||
#endif /*BINARY_OPEN*/
|
||||
#endif /*G_PLATFORM_WIN32*/
|
||||
|
||||
/* If we have O_BINARY, add it to a mode flags set.
|
||||
*/
|
||||
|
@ -58,9 +58,9 @@
|
||||
#include <vips/internal.h>
|
||||
#include <vips/thread.h>
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
/* Sanity checking ... write to this during read tests to make sure we don't
|
||||
* get optimized out.
|
||||
@ -189,15 +189,15 @@ vips_getpagesize( void )
|
||||
static int pagesize = 0;
|
||||
|
||||
if( !pagesize ) {
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
SYSTEM_INFO si;
|
||||
|
||||
GetSystemInfo( &si );
|
||||
|
||||
pagesize = si.dwAllocationGranularity;
|
||||
#else /*OS_WIN32*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
pagesize = getpagesize();
|
||||
#endif /*OS_WIN32*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
#ifdef DEBUG_TOTAL
|
||||
printf( "vips_getpagesize: 0x%x\n", pagesize );
|
||||
|
@ -1123,16 +1123,9 @@ vips__add_mosaic_name( VipsImage *image )
|
||||
{
|
||||
static int global_serial = 0;
|
||||
|
||||
/* Old glibs named this differently.
|
||||
*
|
||||
* TODO(kleisauke): Could we call vips_image_temp_name instead?
|
||||
/* TODO(kleisauke): Could we call vips_image_temp_name instead?
|
||||
*/
|
||||
int serial =
|
||||
#if GLIB_CHECK_VERSION( 2, 30, 0 )
|
||||
g_atomic_int_add( &global_serial, 1 );
|
||||
#else
|
||||
g_atomic_int_exchange_and_add( &global_serial, 1 );
|
||||
#endif
|
||||
int serial = g_atomic_int_add( &global_serial, 1 );
|
||||
|
||||
char name[256];
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
||||
* - add thumbnail_source
|
||||
* 2/6/20
|
||||
* - add subifd pyr support
|
||||
* 27/2/21
|
||||
* - simplify rules re. processing space, colour management and linear
|
||||
* mode
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -624,16 +627,19 @@ vips_thumbnail_build( VipsObject *object )
|
||||
int preshrunk_page_height;
|
||||
double hshrink;
|
||||
double vshrink;
|
||||
VipsInterpretation interpretation;
|
||||
|
||||
/* TRUE if we've done the import of an ICC transform and still need to
|
||||
* export.
|
||||
*/
|
||||
gboolean have_imported;
|
||||
|
||||
/* TRUE if we've premultiplied and need to unpremultiply.
|
||||
/* If we shrink in linear space, we need to return to the input
|
||||
* colourspace after the shrink.
|
||||
*/
|
||||
VipsInterpretation input_interpretation;
|
||||
|
||||
/* The format we need to revert to after unpremultiply.
|
||||
*/
|
||||
gboolean have_premultiplied;
|
||||
VipsBandFormat unpremultiplied_format;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -679,60 +685,78 @@ vips_thumbnail_build( VipsObject *object )
|
||||
in = t[12];
|
||||
}
|
||||
|
||||
/* In linear mode, we import right at the start.
|
||||
*
|
||||
* We also have to import the whole image if it's CMYK, since
|
||||
* vips_colourspace() (see below) doesn't let you specify the fallback
|
||||
* profile.
|
||||
*
|
||||
* This is only going to work for images in device space. If you have
|
||||
* an image in PCS which also has an attached profile, strange things
|
||||
* will happen.
|
||||
/* In linear mode, we need to transform to a linear space before
|
||||
* vips_resize().
|
||||
*/
|
||||
have_imported = FALSE;
|
||||
if( thumbnail->linear &&
|
||||
in->Coding == VIPS_CODING_NONE &&
|
||||
(in->BandFmt == VIPS_FORMAT_UCHAR ||
|
||||
in->BandFmt == VIPS_FORMAT_USHORT) &&
|
||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||
thumbnail->import_profile) ) {
|
||||
g_info( "importing to XYZ PCS" );
|
||||
if( thumbnail->import_profile )
|
||||
g_info( "fallback input profile %s",
|
||||
thumbnail->import_profile );
|
||||
if( thumbnail->linear ) {
|
||||
/* If we are doing colour management (there's an import
|
||||
* profile), then we can use XYZ PCS as the resize space.
|
||||
*/
|
||||
if( in->Coding == VIPS_CODING_NONE &&
|
||||
(in->BandFmt == VIPS_FORMAT_UCHAR ||
|
||||
in->BandFmt == VIPS_FORMAT_USHORT) &&
|
||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||
thumbnail->import_profile) ) {
|
||||
g_info( "importing to XYZ PCS" );
|
||||
if( thumbnail->import_profile )
|
||||
g_info( "fallback input profile %s",
|
||||
thumbnail->import_profile );
|
||||
|
||||
if( vips_icc_import( in, &t[1],
|
||||
"input_profile", thumbnail->import_profile,
|
||||
"embedded", TRUE,
|
||||
"intent", thumbnail->intent,
|
||||
"pcs", VIPS_PCS_XYZ,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( vips_icc_import( in, &t[1],
|
||||
"input_profile", thumbnail->import_profile,
|
||||
"embedded", TRUE,
|
||||
"intent", thumbnail->intent,
|
||||
"pcs", VIPS_PCS_XYZ,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[1];
|
||||
|
||||
in = t[1];
|
||||
have_imported = TRUE;
|
||||
}
|
||||
else {
|
||||
/* Otherwise, use scRGB or GREY16 for linear shrink.
|
||||
*/
|
||||
VipsInterpretation interpretation;
|
||||
|
||||
have_imported = TRUE;
|
||||
/* Note the interpretation we will revert to after
|
||||
* linear.
|
||||
*/
|
||||
input_interpretation = in->Type;
|
||||
|
||||
if( in->Bands < 3 )
|
||||
interpretation = VIPS_INTERPRETATION_GREY16;
|
||||
else
|
||||
interpretation = VIPS_INTERPRETATION_scRGB;
|
||||
|
||||
g_info( "converting to processing space %s",
|
||||
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||
interpretation ) );
|
||||
if( vips_colourspace( in, &t[2], interpretation,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[2];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* In non-linear mode, use sRGB or B_W as the processing
|
||||
* space.
|
||||
*/
|
||||
VipsInterpretation interpretation;
|
||||
|
||||
/* To the processing colourspace. This will unpack LABQ, import CMYK,
|
||||
* etc.
|
||||
*
|
||||
* If this is a CMYK image, we need to set have_imported since we only
|
||||
* want to export at the end.
|
||||
*/
|
||||
if( in->Type == VIPS_INTERPRETATION_CMYK )
|
||||
have_imported = TRUE;
|
||||
if( thumbnail->linear )
|
||||
interpretation = VIPS_INTERPRETATION_scRGB;
|
||||
else if( in->Bands < 3 )
|
||||
interpretation = VIPS_INTERPRETATION_B_W;
|
||||
else
|
||||
interpretation = VIPS_INTERPRETATION_sRGB;
|
||||
g_info( "converting to processing space %s",
|
||||
vips_enum_nick( VIPS_TYPE_INTERPRETATION, interpretation ) );
|
||||
if( vips_colourspace( in, &t[2], interpretation, NULL ) )
|
||||
return( -1 );
|
||||
in = t[2];
|
||||
if( in->Bands < 3 )
|
||||
interpretation = VIPS_INTERPRETATION_B_W;
|
||||
else
|
||||
interpretation = VIPS_INTERPRETATION_sRGB;
|
||||
|
||||
g_info( "converting to processing space %s",
|
||||
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||
interpretation ) );
|
||||
if( vips_colourspace( in, &t[2], interpretation,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[2];
|
||||
}
|
||||
|
||||
/* Shrink to preshrunk_page_height, so we work for multi-page images.
|
||||
*/
|
||||
@ -751,23 +775,23 @@ vips_thumbnail_build( VipsObject *object )
|
||||
vshrink = (double) in->Ysize / target_image_height;
|
||||
}
|
||||
|
||||
/* vips_premultiply() makes a float image, so when we unpremultiply
|
||||
* below we must cast back to the original format. Use NOTSET to
|
||||
* meran no pre/unmultiply.
|
||||
*/
|
||||
unpremultiplied_format = VIPS_FORMAT_NOTSET;
|
||||
|
||||
/* If there's an alpha, we have to premultiply before shrinking. See
|
||||
* https://github.com/libvips/libvips/issues/291
|
||||
*/
|
||||
have_premultiplied = FALSE;
|
||||
if( vips_image_hasalpha( in ) &&
|
||||
hshrink != 1.0 &&
|
||||
vshrink != 1.0 ) {
|
||||
g_info( "premultiplying alpha" );
|
||||
unpremultiplied_format = in->BandFmt;
|
||||
|
||||
if( vips_premultiply( in, &t[3], NULL ) )
|
||||
return( -1 );
|
||||
have_premultiplied = TRUE;
|
||||
|
||||
/* vips_premultiply() makes a float image. When we
|
||||
* vips_unpremultiply() below, we need to cast back to the
|
||||
* pre-premultiply format.
|
||||
*/
|
||||
unpremultiplied_format = in->BandFmt;
|
||||
in = t[3];
|
||||
}
|
||||
|
||||
@ -777,6 +801,14 @@ vips_thumbnail_build( VipsObject *object )
|
||||
return( -1 );
|
||||
in = t[4];
|
||||
|
||||
if( unpremultiplied_format != VIPS_FORMAT_NOTSET ) {
|
||||
g_info( "unpremultiplying alpha" );
|
||||
if( vips_unpremultiply( in, &t[5], NULL ) ||
|
||||
vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) )
|
||||
return( -1 );
|
||||
in = t[6];
|
||||
}
|
||||
|
||||
/* Only set page-height if we have more than one page, or this could
|
||||
* accidentally turn into an animated image later.
|
||||
*/
|
||||
@ -792,21 +824,12 @@ vips_thumbnail_build( VipsObject *object )
|
||||
VIPS_META_PAGE_HEIGHT, output_page_height );
|
||||
}
|
||||
|
||||
if( have_premultiplied ) {
|
||||
g_info( "unpremultiplying alpha" );
|
||||
if( vips_unpremultiply( in, &t[5], NULL ) ||
|
||||
vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) )
|
||||
return( -1 );
|
||||
in = t[6];
|
||||
}
|
||||
|
||||
/* Colour management.
|
||||
*
|
||||
* If we've already imported, just export. Otherwise, we're in
|
||||
* device space and we need a combined import/export to transform to
|
||||
* the target space.
|
||||
*/
|
||||
if( have_imported ) {
|
||||
/* We've already imported, just export. Go to sRGB if there's
|
||||
* no export profile.
|
||||
*/
|
||||
if( thumbnail->export_profile ||
|
||||
vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
|
||||
g_info( "exporting to device space with a profile" );
|
||||
@ -825,21 +848,54 @@ vips_thumbnail_build( VipsObject *object )
|
||||
in = t[7];
|
||||
}
|
||||
}
|
||||
else if( thumbnail->export_profile &&
|
||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||
thumbnail->import_profile) ) {
|
||||
else if( thumbnail->export_profile ) {
|
||||
/* Not imported, but we are doing colour management. Transform
|
||||
* to the output space.
|
||||
*/
|
||||
g_info( "transforming to %s", thumbnail->export_profile );
|
||||
if( thumbnail->import_profile )
|
||||
g_info( "fallback input profile %s",
|
||||
thumbnail->import_profile );
|
||||
|
||||
if( vips_icc_transform( in, &t[7],
|
||||
thumbnail->export_profile,
|
||||
"input_profile", thumbnail->import_profile,
|
||||
"intent", thumbnail->intent,
|
||||
"embedded", TRUE,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
/* If there's some kind of import profile, we can transform to
|
||||
* the output. Otherwise we have to convert to PCS and then
|
||||
* export.
|
||||
*/
|
||||
if( thumbnail->import_profile ||
|
||||
(vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ||
|
||||
thumbnail->import_profile) ) {
|
||||
g_info( "transforming with supplied profiles" );
|
||||
if( vips_icc_transform( in, &t[7],
|
||||
thumbnail->export_profile,
|
||||
"input_profile", thumbnail->import_profile,
|
||||
"intent", thumbnail->intent,
|
||||
"embedded", TRUE,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
in = t[7];
|
||||
}
|
||||
else {
|
||||
g_info( "exporting with %s",
|
||||
thumbnail->export_profile );
|
||||
if( vips_colourspace( in, &t[7],
|
||||
VIPS_INTERPRETATION_XYZ, NULL ) ||
|
||||
vips_icc_export( t[7], &t[10],
|
||||
"output_profile",
|
||||
thumbnail->export_profile,
|
||||
"intent", thumbnail->intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[10];
|
||||
}
|
||||
}
|
||||
else if( thumbnail->linear ) {
|
||||
/* Linear mode, no colour management. We went to scRGB for
|
||||
* processing, so we now revert to the input colourspace.
|
||||
*/
|
||||
g_info( "reverting to input space %s",
|
||||
vips_enum_nick( VIPS_TYPE_INTERPRETATION,
|
||||
input_interpretation ) );
|
||||
if( vips_colourspace( in, &t[7],
|
||||
input_interpretation, NULL ) )
|
||||
return( -1 );
|
||||
in = t[7];
|
||||
}
|
||||
|
||||
@ -1368,7 +1424,7 @@ vips_thumbnail_buffer_init( VipsThumbnailBuffer *buffer )
|
||||
* * @intent: #VipsIntent, rendering intent
|
||||
* * @option_string: %gchararray, extra loader options
|
||||
*
|
||||
* Exacty as vips_thumbnail(), but read from a memory buffer. One extra
|
||||
* Exactly as vips_thumbnail(), but read from a memory buffer. One extra
|
||||
* optional argument, @option_string, lets you pass options to the underlying
|
||||
* loader.
|
||||
*
|
||||
@ -1564,7 +1620,7 @@ vips_thumbnail_source_init( VipsThumbnailSource *source )
|
||||
* * @intent: #VipsIntent, rendering intent
|
||||
* * @option_string: %gchararray, extra loader options
|
||||
*
|
||||
* Exacty as vips_thumbnail(), but read from a source. One extra
|
||||
* Exactly as vips_thumbnail(), but read from a source. One extra
|
||||
* optional argument, @option_string, lets you pass options to the underlying
|
||||
* loader.
|
||||
*
|
||||
@ -1671,7 +1727,7 @@ vips_thumbnail_image_init( VipsThumbnailImage *image )
|
||||
* * @export_profile: %gchararray, export ICC profile
|
||||
* * @intent: #VipsIntent, rendering intent
|
||||
*
|
||||
* Exacty as vips_thumbnail(), but read from an existing image.
|
||||
* Exactly as vips_thumbnail(), but read from an existing image.
|
||||
*
|
||||
* This operation
|
||||
* is not able to exploit shrink-on-load features of image load libraries, so
|
||||
|
@ -42,6 +42,9 @@ BMP_FILE = os.path.join(IMAGES, "MARBLES.BMP")
|
||||
NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz")
|
||||
ICO_FILE = os.path.join(IMAGES, "favicon.ico")
|
||||
AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif")
|
||||
HEIC_FILE = os.path.join(IMAGES, "heic-orientation-6.heic")
|
||||
RGBA_FILE = os.path.join(IMAGES, "rgba.png")
|
||||
RGBA_CORRECT_FILE = os.path.join(IMAGES, "rgba-correct.ppm")
|
||||
MOSAIC_FILES = [os.path.join(IMAGES, "cd1.1.jpg"), os.path.join(IMAGES, "cd1.2.jpg"),
|
||||
os.path.join(IMAGES, "cd2.1.jpg"), os.path.join(IMAGES, "cd2.2.jpg"),
|
||||
os.path.join(IMAGES, "cd3.1.jpg"), os.path.join(IMAGES, "cd3.2.jpg"),
|
||||
|
5
test/test-suite/images/rgba-correct.ppm
Normal file
5
test/test-suite/images/rgba-correct.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
test/test-suite/images/rgba.png
Normal file
BIN
test/test-suite/images/rgba.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
@ -2,7 +2,8 @@
|
||||
import pytest
|
||||
|
||||
import pyvips
|
||||
from helpers import JPEG_FILE, OME_FILE, AVIF_FILE, TIF_FILE, all_formats, have
|
||||
from helpers import JPEG_FILE, OME_FILE, HEIC_FILE, TIF_FILE, all_formats, \
|
||||
have, RGBA_FILE, RGBA_CORRECT_FILE, AVIF_FILE
|
||||
|
||||
|
||||
# Run a function expecting a complex image on a two-band image
|
||||
@ -193,6 +194,11 @@ class TestResample:
|
||||
im2 = pyvips.Image.thumbnail_buffer(buf, 100)
|
||||
assert abs(im1.avg() - im2.avg()) < 1
|
||||
|
||||
# linear shrink should work on rgba images
|
||||
im1 = pyvips.Image.thumbnail(RGBA_FILE, 64, linear=True)
|
||||
im2 = pyvips.Image.new_from_file(RGBA_CORRECT_FILE)
|
||||
assert abs(im1.flatten(background=255).avg() - im2.avg()) < 1
|
||||
|
||||
if have("heifload"):
|
||||
# this image is orientation 6 ... thumbnail should flip it
|
||||
im = pyvips.Image.new_from_file(AVIF_FILE)
|
||||
|
24
tools/vips.c
24
tools/vips.c
@ -101,9 +101,9 @@
|
||||
#include <vips/vips7compat.h>
|
||||
#endif
|
||||
|
||||
#ifdef OS_WIN32
|
||||
#ifdef G_OS_WIN32
|
||||
#define strcasecmp(a,b) _stricmp(a,b)
|
||||
#endif
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
static char *main_option_plugin = NULL;
|
||||
static gboolean main_option_version;
|
||||
@ -458,11 +458,11 @@ parse_options( GOptionContext *context, int *argc, char **argv )
|
||||
"OPER", _( "execute vips operation OPER" ) );
|
||||
g_option_context_set_summary( context, vips_buf_all( &buf ) );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
if( !g_option_context_parse_strv( context, &argv, &error ) )
|
||||
#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( !g_option_context_parse( context, argc, &argv, &error ) )
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
{
|
||||
if( error ) {
|
||||
fprintf( stderr, "%s\n", error->message );
|
||||
@ -531,9 +531,9 @@ main( int argc, char **argv )
|
||||
/* On Windows, argv is ascii-only .. use this to get a utf-8 version of
|
||||
* the args.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
argv = g_win32_get_command_line();
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
#ifdef DEBUG_FATAL
|
||||
/* Set masks for debugging ... stop on any problem.
|
||||
@ -582,11 +582,11 @@ main( int argc, char **argv )
|
||||
*/
|
||||
g_option_context_set_help_enabled( context, FALSE );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
if( !g_option_context_parse_strv( context, &argv, &error ) )
|
||||
#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( !g_option_context_parse( context, &argc, &argv, &error ) )
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
{
|
||||
if( error ) {
|
||||
fprintf( stderr, "%s\n", error->message );
|
||||
@ -753,9 +753,9 @@ main( int argc, char **argv )
|
||||
|
||||
g_option_context_free( context );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
g_strfreev( argv );
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
vips_shutdown();
|
||||
|
||||
|
@ -141,9 +141,9 @@ main( int argc, char **argv )
|
||||
/* On Windows, argv is ascii-only .. use this to get a utf-8 version of
|
||||
* the args.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
argv = g_win32_get_command_line();
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
context = g_option_context_new(
|
||||
_( "vipsedit - edit vips file header" ) );
|
||||
@ -153,11 +153,11 @@ main( int argc, char **argv )
|
||||
g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE );
|
||||
g_option_context_set_main_group( context, main_group );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
if( !g_option_context_parse_strv( context, &argv, &error ) )
|
||||
#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( !g_option_context_parse( context, &argc, &argv, &error ) )
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
{
|
||||
vips_g_error( &error );
|
||||
|
||||
@ -272,9 +272,9 @@ main( int argc, char **argv )
|
||||
|
||||
g_option_context_free( context );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
g_strfreev( argv );
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
vips_shutdown();
|
||||
|
||||
|
@ -180,9 +180,9 @@ main( int argc, char *argv[] )
|
||||
/* On Windows, argv is ascii-only .. use this to get a utf-8 version of
|
||||
* the args.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
argv = g_win32_get_command_line();
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
context = g_option_context_new( _( "- print image header" ) );
|
||||
main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL );
|
||||
@ -191,11 +191,11 @@ main( int argc, char *argv[] )
|
||||
g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE );
|
||||
g_option_context_set_main_group( context, main_group );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
if( !g_option_context_parse_strv( context, &argv, &error ) )
|
||||
#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( !g_option_context_parse( context, &argc, &argv, &error ) )
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
{
|
||||
if( error ) {
|
||||
fprintf( stderr, "%s\n", error->message );
|
||||
@ -247,9 +247,9 @@ main( int argc, char *argv[] )
|
||||
|
||||
/* We don't free this on error exit, sadly.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
g_strfreev( argv );
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
vips_shutdown();
|
||||
|
||||
|
@ -500,9 +500,9 @@ main( int argc, char **argv )
|
||||
/* On Windows, argv is ascii-only .. use this to get a utf-8 version of
|
||||
* the args.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
argv = g_win32_get_command_line();
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
context = g_option_context_new( _( "- thumbnail generator" ) );
|
||||
|
||||
@ -512,11 +512,11 @@ main( int argc, char **argv )
|
||||
g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE );
|
||||
g_option_context_set_main_group( context, main_group );
|
||||
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
if( !g_option_context_parse_strv( context, &argv, &error ) )
|
||||
#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#else /*!G_OS_WIN32*/
|
||||
if( !g_option_context_parse( context, &argc, &argv, &error ) )
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
{
|
||||
if( error ) {
|
||||
fprintf( stderr, "%s\n", error->message );
|
||||
@ -563,9 +563,9 @@ main( int argc, char **argv )
|
||||
|
||||
/* We don't free this on error exit, sadly.
|
||||
*/
|
||||
#ifdef HAVE_G_WIN32_GET_COMMAND_LINE
|
||||
#ifdef G_OS_WIN32
|
||||
g_strfreev( argv );
|
||||
#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/
|
||||
#endif /*G_OS_WIN32*/
|
||||
|
||||
vips_shutdown();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user