Merge branch 'master' into improve-detection-of-bad-profiles
This commit is contained in:
commit
6a0e5c26db
|
@ -56,19 +56,15 @@ 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')
|
||||
run:
|
||||
brew install
|
||||
autoconf automake libtool
|
||||
gtk-doc gobject-introspection
|
||||
cfitsio fftw giflib
|
||||
glib libexif libgsf
|
||||
libheif libjpeg-turbo libmatio
|
||||
librsvg libspng libtiff
|
||||
little-cms2 openexr openslide
|
||||
orc pango poppler webp
|
||||
run: |
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install autoconf automake libtool fftw fontconfig gtk-doc gobject-introspection glib libexif libgsf little-cms2 orc pango
|
||||
brew install cfitsio imagemagick@6 libheif libjpeg-turbo libmatio librsvg libspng libtiff openexr openjpeg openslide poppler webp
|
||||
|
||||
- name: Install Clang 10
|
||||
env:
|
||||
|
@ -93,7 +89,7 @@ jobs:
|
|||
if: contains(matrix.os, 'macos')
|
||||
run: |
|
||||
echo "JOBS=$(sysctl -n hw.logicalcpu)" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH=/usr/local/opt/jpeg-turbo/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH=/usr/local/opt/jpeg-turbo/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig:/usr/local/opt/imagemagick@6/lib/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Prepare sanitizers
|
||||
if: matrix.sanitize
|
||||
|
|
|
@ -41,6 +41,7 @@ Vips-8.0.typelib
|
|||
*.pyc
|
||||
*.pyo
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
aclocal.m4
|
||||
config.log
|
||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -23,4 +23,6 @@ Nicolas Robidoux contributed optimized bilinear and bicubic code to
|
|||
the VipsInterpolate class and, with Chantal Racette and Adam Turcotte,
|
||||
contributed the novel LBB, Nohalo and VSQBS interpolators.
|
||||
|
||||
Lovell Fuller and Kleis Auke Wolthuizen made many contributions and fixes.
|
||||
|
||||
Many other active contributors, see https://github.com/libvips/libvips/graphs/contributors
|
||||
|
|
15
ChangeLog
15
ChangeLog
|
@ -20,19 +20,24 @@
|
|||
- 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
|
||||
- add black_point_compensation flag for icc transforms
|
||||
- add "rgba" flag to vips_text() to enable full colour text rendering
|
||||
|
||||
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]
|
||||
- revise premultiply, again [jjonesrs]
|
||||
- revise profile handling in vipsthumbnail
|
||||
- fix issue thumbnailing RGBA images in linear mode [jjonesrs]
|
||||
- improve vipsthumbnail profile handling
|
||||
- fix tiff deflate predictor setting [Adios]
|
||||
- fix vector path for composite on i386 [kleisauke]
|
||||
|
||||
18/12/20 started 8.10.5
|
||||
- fix potential /0 in animated webp load [lovell]
|
||||
|
|
28
README.md
28
README.md
|
@ -22,7 +22,7 @@ operations, frequency filtering, colour, resampling,
|
|||
statistics and others. It supports a large range of [numeric
|
||||
types](https://libvips.github.io/libvips/API/current/VipsImage.html#VipsBandFormat),
|
||||
from 8-bit int to 128-bit complex. Images can have any number of bands.
|
||||
It supports a good range of image formats, including JPEG, TIFF, PNG,
|
||||
It supports a good range of image formats, including JPEG, JPEG2000, TIFF, PNG,
|
||||
WebP, HEIC, AVIF, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM / PGM / PFM,
|
||||
CSV, GIF, Analyze, NIfTI, DeepZoom, and OpenSlide. It can also load images
|
||||
via ImageMagick or GraphicsMagick, letting it work with formats like DICOM.
|
||||
|
@ -116,6 +116,13 @@ Debug build:
|
|||
make
|
||||
make install
|
||||
|
||||
# Built-in loaders
|
||||
|
||||
libvips has a number of built-in loaders and savers. You can disable these if
|
||||
you wish, for example:
|
||||
|
||||
./configure --prefix=/Users/john/vips --without-nsgif --without-ppm
|
||||
|
||||
# Dependencies
|
||||
|
||||
libvips has to have `libglib2.0-dev` and `libexpat1-dev`. Other dependencies
|
||||
|
@ -128,14 +135,14 @@ libraries automatically. See `./configure --help` for a set of flags to
|
|||
control library detection. Packages are generally found with `pkg-config`,
|
||||
so make sure that is working.
|
||||
|
||||
Libraries like giflib and nifti do not use `pkg-config` so libvips will also
|
||||
Libraries like nifti do not use `pkg-config` so libvips will also
|
||||
look for them in the default path and in `$prefix`. If you have installed
|
||||
your own versions of these libraries in a different location, libvips will
|
||||
not see them. Use switches to libvips configure like:
|
||||
|
||||
./configure --prefix=/Users/john/vips \
|
||||
--with-giflib-includes=/opt/local/include \
|
||||
--with-giflib-libraries=/opt/local/lib
|
||||
--with-nifti-includes=/opt/local/include \
|
||||
--with-nifti-libraries=/opt/local/lib
|
||||
|
||||
or perhaps:
|
||||
|
||||
|
@ -151,11 +158,6 @@ The IJG JPEG library. Use the `-turbo` version if you can.
|
|||
|
||||
If available, libvips adds support for EXIF metadata in JPEG files.
|
||||
|
||||
### giflib
|
||||
|
||||
The standard gif loader. If this is not present, vips will try to load gifs
|
||||
via imagemagick instead.
|
||||
|
||||
### librsvg
|
||||
|
||||
The usual SVG loader. If this is not present, vips will try to load SVGs
|
||||
|
@ -241,10 +243,10 @@ If you are going to be using libvips with untrusted images, perhaps in a
|
|||
web server, for example, you should consider the security implications of
|
||||
enabling a package with such a large attack surface.
|
||||
|
||||
### pangoft2
|
||||
### pangocairo
|
||||
|
||||
If available, libvips adds support for text rendering. You need the
|
||||
package pangoft2 in `pkg-config --list-all`.
|
||||
package pangocairo in `pkg-config --list-all`.
|
||||
|
||||
### orc-0.4
|
||||
|
||||
|
@ -272,6 +274,10 @@ If available, vips can load and save NIfTI images.
|
|||
If available, libvips will directly read (but not write, sadly)
|
||||
OpenEXR images.
|
||||
|
||||
### OpenJPEG
|
||||
|
||||
If available, libvips will read and write JPEG2000 images.
|
||||
|
||||
### OpenSlide
|
||||
|
||||
If available, libvips can load OpenSlide-supported virtual slide
|
||||
|
|
589
configure.ac
589
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
|
||||
|
@ -219,7 +190,6 @@ AC_PROG_CC_STDC
|
|||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AM_WITH_DMALLOC
|
||||
|
||||
AC_ARG_WITH([doxygen],
|
||||
AS_HELP_STRING([--without-doxygen], [build without doxygen (default: test)]))
|
||||
|
@ -286,7 +256,7 @@ AM_GLIB_GNU_GETTEXT
|
|||
# [ax_gcc_version_option=yes],
|
||||
# [ax_gcc_version_option=no]
|
||||
# )
|
||||
AC_MSG_CHECKING([for gcc version])
|
||||
AC_MSG_CHECKING([for $CC version])
|
||||
GCC_VERSION=""
|
||||
version=$($CC -dumpversion)
|
||||
if test $? = 0; then
|
||||
|
@ -340,7 +310,7 @@ AC_TYPE_SIZE_T
|
|||
|
||||
# g++/gcc 4.x and 5.x have rather broken vector support ... 5.4.1 seems to
|
||||
# work, but 5.4.0 fails to even compile
|
||||
AC_MSG_CHECKING([for gcc with working vector support])
|
||||
AC_MSG_CHECKING([for $CC with working vector support])
|
||||
if test x"$GCC_VERSION_MAJOR" != x"4" -a x"$GCC_VERSION_MAJOR" != x"5"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
|
@ -353,7 +323,7 @@ if test x"$ax_cv_have_var_attribute_vector_size" = x"yes"; then
|
|||
AC_MSG_CHECKING([for C++ vector shuffle])
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_TRY_COMPILE([
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float))));
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float)),aligned(16)));
|
||||
],[
|
||||
v4f f; f[3] = 99;
|
||||
],[
|
||||
|
@ -376,7 +346,7 @@ if test x"$have_vector_shuffle" = x"yes"; then
|
|||
AC_MSG_CHECKING([for C++ vector arithmetic])
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_TRY_COMPILE([
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float))));
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float)),aligned(16)));
|
||||
],[
|
||||
v4f f = {1, 2, 3, 4}; f *= 12.0;
|
||||
v4f g = {5, 6, 7, 8}; f = g > 0 ? g : -1 * g;
|
||||
|
@ -396,7 +366,7 @@ if test x"$have_vector_arith" = x"yes"; then
|
|||
AC_MSG_CHECKING([for C++ signed constants in vector templates])
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_TRY_COMPILE([
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float))));
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float)),aligned(16)));
|
||||
template <typename T>
|
||||
static void
|
||||
h( v4f B )
|
||||
|
@ -423,7 +393,7 @@ fi
|
|||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS([getcwd gettimeofday getwd memset munmap putenv realpath strcasecmp strchr strcspn strdup strerror strrchr strspn vsnprintf realpath mkstemp mktemp random rand sysconf atexit])
|
||||
AC_CHECK_FUNCS([getcwd gettimeofday getwd memset munmap putenv realpath strcasecmp strchr strcspn strdup strerror strrchr strspn vsnprintf realpath mkstemp mktemp random rand sysconf atexit _aligned_malloc posix_memalign memalign])
|
||||
AC_CHECK_LIB(m,cbrt,[AC_DEFINE(HAVE_CBRT,1,[have cbrt() in libm.])])
|
||||
AC_CHECK_LIB(m,hypot,[AC_DEFINE(HAVE_HYPOT,1,[have hypot() in libm.])])
|
||||
AC_CHECK_LIB(m,atan2,[AC_DEFINE(HAVE_ATAN2,1,[have atan2() in libm.])])
|
||||
|
@ -435,20 +405,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 +429,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 +454,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 +481,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 +506,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 +572,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 +630,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 +642,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 +668,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 +685,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 +699,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 +707,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 +730,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 +750,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 +766,40 @@ 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"
|
||||
|
||||
# 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)]))
|
||||
|
@ -790,13 +813,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 +840,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 +861,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 +890,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 +908,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 +927,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 +953,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 +984,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,9 +1003,22 @@ 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
|
||||
|
||||
AC_ARG_WITH([nsgif],
|
||||
AS_HELP_STRING([--without-nsgif], [build without nsgif load (default: with)]))
|
||||
|
||||
if test x"$with_nsgif" != x"no"; then
|
||||
AC_DEFINE(HAVE_NSGIF,1,[define to build nsgif load support.])
|
||||
with_nsgif=yes
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_NSGIF, [test x"$with_nsgif" = x"yes"])
|
||||
|
||||
AC_ARG_WITH([ppm],
|
||||
AS_HELP_STRING([--without-ppm], [build without ppm (default: with)]))
|
||||
|
||||
|
@ -1004,6 +1059,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
|
||||
|
@ -1022,23 +1080,49 @@ if test x"$with_libwebp" != x"no"; then
|
|||
)
|
||||
fi
|
||||
|
||||
# pangoft2
|
||||
AC_ARG_WITH([pangoft2],
|
||||
AS_HELP_STRING([--without-pangoft2],
|
||||
[build without pangoft2 (default: test)]))
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $LIBWEBP_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $LIBWEBP_LIBS"
|
||||
|
||||
if test x"$with_pangoft2" != x"no"; then
|
||||
PKG_CHECK_MODULES(PANGOFT2, pangoft2,
|
||||
[AC_DEFINE(HAVE_PANGOFT2,1,[define if you have pangoft2 installed.])
|
||||
with_pangoft2=yes
|
||||
PACKAGES_USED="$PACKAGES_USED pangoft2"
|
||||
# pangocairo for text rendering
|
||||
AC_ARG_WITH([pangocairo],
|
||||
AS_HELP_STRING([--without-pangocairo],
|
||||
[build without pangocairo (default: test)]))
|
||||
|
||||
if test x"$with_pangocairo" != x"no"; then
|
||||
PKG_CHECK_MODULES(PANGOCAIRO, pangocairo,
|
||||
[AC_DEFINE(HAVE_PANGOCAIRO,1,[define if you have pangocairo installed.])
|
||||
with_pangocairo=yes
|
||||
PACKAGES_USED="$PACKAGES_USED pangocairo"
|
||||
],
|
||||
[AC_MSG_WARN([pangoft2 not found; disabling pangoft2 support])
|
||||
with_pangoft2=no
|
||||
[AC_MSG_WARN([pangocairo not found; disabling pangocairo support])
|
||||
with_pangocairo=no
|
||||
]
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $PANGOCAIRO_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $PANGOCAIRO_LIBS"
|
||||
|
||||
# font file support with fontconfig
|
||||
AC_ARG_WITH([fontconfig],
|
||||
AS_HELP_STRING([--without-fontconfig],
|
||||
[build without fontconfig (default: test)]))
|
||||
|
||||
if test x"$with_pangocairo" != x"no" -a x"$with_fontconfig" != x"no"; then
|
||||
PKG_CHECK_MODULES(FONTCONFIG, fontconfig,
|
||||
[AC_DEFINE(HAVE_FONTCONFIG,1,[define if you have fontconfig installed.])
|
||||
with_fontconfig=yes
|
||||
PACKAGES_USED="$PACKAGES_USED fontconfig"
|
||||
],
|
||||
[AC_MSG_WARN([fontconfig not found; disabling fontconfig support])
|
||||
with_fontconfig=no
|
||||
]
|
||||
)
|
||||
fi
|
||||
|
||||
VIPS_CFLAGS="$VIPS_CFLAGS $FONTCONFIG_CFLAGS"
|
||||
VIPS_LIBS="$VIPS_LIBS $FONTCONFIG_LIBS"
|
||||
|
||||
# look for TIFF with pkg-config ... fall back to our tester
|
||||
# pkgconfig support for libtiff starts with libtiff-4
|
||||
AC_ARG_WITH([tiff],
|
||||
|
@ -1074,14 +1158,9 @@ if test x"$with_tiff" != x"no"; then
|
|||
INCLUDES="$save_INCLUDES"
|
||||
fi
|
||||
|
||||
# giflib
|
||||
FIND_GIFLIB(
|
||||
[with_giflib="yes (found by search)"
|
||||
],
|
||||
[AC_MSG_WARN([giflib not found; disabling direct GIF support])
|
||||
with_giflib=no
|
||||
]
|
||||
)
|
||||
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"
|
||||
|
@ -1106,6 +1185,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
|
||||
|
@ -1136,11 +1218,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)]))
|
||||
|
@ -1159,6 +1245,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)]))
|
||||
|
@ -1191,11 +1280,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)]))
|
||||
|
@ -1223,6 +1316,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])
|
||||
|
@ -1230,14 +1326,48 @@ 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 $GIFLIB_INCLUDES $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 $GIFLIB_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 support: $with_ppm, 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, file import with niftiio: $with_nifti, file import with libheif: $with_heif, file import with OpenEXR: $with_OpenEXR, file import with OpenSlide: $with_openslide, file import with matio: $with_matio, PDF import with PDFium: $with_pdfium, PDF import with poppler-glib: $with_poppler, SVG import with librsvg-2.0: $with_rsvg, zlib: $with_zlib, file import with cfitsio: $with_cfitsio, file import/export with libwebp: $with_libwebp, text rendering with pangoft2: $with_pangoft2, file import/export with libspng: $with_libspng, file import/export with libpng: $with_png, support 8bpp PNG quantisation: $with_imagequant, file import/export with libtiff: $with_tiff, file import/export with giflib: $with_giflib, file import/export 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 pangocairo: $with_pangocairo, \
|
||||
font file support with fontconfig: $with_fontconfig, \
|
||||
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)
|
||||
|
||||
|
@ -1254,108 +1384,103 @@ 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/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/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
|
||||
])
|
||||
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 support: $with_radiance
|
||||
enable analyze support: $with_analyze
|
||||
enable PPM support: $with_ppm
|
||||
## 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
|
||||
file import with niftiio: $with_nifti
|
||||
file import with libheif: $with_heif
|
||||
file import with OpenEXR: $with_OpenEXR
|
||||
file import with OpenSlide: $with_openslide
|
||||
(requires openslide-3.3.0 or later)
|
||||
file import with matio: $with_matio
|
||||
PDF import with PDFium: $with_pdfium
|
||||
PDF import with poppler-glib: $with_poppler
|
||||
(requires poppler-glib 0.16.0 or later)
|
||||
SVG import with librsvg-2.0: $with_rsvg
|
||||
(requires librsvg-2.0 2.34.0 or later)
|
||||
zlib: $with_zlib
|
||||
file import with cfitsio: $with_cfitsio
|
||||
file import/export with libwebp: $with_libwebp
|
||||
(requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later)
|
||||
text rendering with pangoft2: $with_pangoft2
|
||||
file import/export with libspng: $with_libspng
|
||||
(requires libspng-0.6 or later)
|
||||
file import/export with libpng: $with_png
|
||||
(requires libpng-1.2.9 or later)
|
||||
support 8bpp PNG quantisation: $with_imagequant
|
||||
(requires libimagequant)
|
||||
file import/export with libtiff: $with_tiff
|
||||
file import/export with giflib: $with_giflib
|
||||
file import/export 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 pangocairo: $with_pangocairo
|
||||
font file support with fontconfig: $with_fontconfig
|
||||
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
|
||||
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
|
||||
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
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,6 +42,9 @@ install-htmlDATA:
|
|||
-mkdir -p $(DESTDIR)$(htmldir)
|
||||
-cp -r html $(DESTDIR)$(htmldir)
|
||||
|
||||
uninstall-htmlDATA:
|
||||
rm -rf $(DESTDIR)$(htmldir)/html
|
||||
|
||||
EXTRA_DIST = \
|
||||
README.md \
|
||||
vips-operators.cpp \
|
||||
|
|
|
@ -5,9 +5,10 @@ pkginclude_HEADERS = \
|
|||
VConnection8.h \
|
||||
vips8
|
||||
|
||||
vips-operators.h:
|
||||
echo "// headers for vips operations" > vips-operators.h; \
|
||||
echo -n "// " >> vips-operators.h; \
|
||||
date >> vips-operators.h; \
|
||||
echo "// this file is generated automatically, do not edit!" >> vips-operators.h; \
|
||||
./../../gen-operators.py -g h >> vips-operators.h
|
||||
vips-operators:
|
||||
echo "// headers for vips operations" > vips-operators; \
|
||||
echo "// paste this file into VImage8.h, do not leave in repo" > vips-operators; \
|
||||
echo -n "// " >> vips-operators; \
|
||||
date >> vips-operators; \
|
||||
echo "// this file is generated automatically, do not edit!" >> vips-operators; \
|
||||
./../../gen-operators.py -g h >> vips-operators
|
||||
|
|
|
@ -600,6 +600,29 @@ public:
|
|||
static_cast<int>( value.size() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of an double array metadata item on an image.
|
||||
*
|
||||
* A copy of the array is taken.
|
||||
*/
|
||||
void
|
||||
set( const char *field, double *value, int n )
|
||||
{
|
||||
vips_image_set_array_double( this->get_image(), field, value, n );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of an double array metadata item on an image.
|
||||
*
|
||||
* A copy of the array is taken.
|
||||
*/
|
||||
void
|
||||
set( const char *field, std::vector<double> value )
|
||||
{
|
||||
vips_image_set_array_double( this->get_image(), field, &value[0],
|
||||
static_cast<int>( value.size() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a double metadata item on an image.
|
||||
*/
|
||||
|
@ -695,6 +718,40 @@ public:
|
|||
return( vector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a metadata item as an array of doubles. Do not free
|
||||
* the result.
|
||||
*
|
||||
* If the item is not of this type, an exception is thrown.
|
||||
*/
|
||||
void
|
||||
get_array_double( const char *field, double **out, int *n ) const
|
||||
{
|
||||
if( vips_image_get_array_double( this->get_image(),
|
||||
field, out, n ) )
|
||||
throw( VError() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a metadata item as an array of doubles.
|
||||
*
|
||||
* If the item is not of this type, an exception is thrown.
|
||||
*/
|
||||
std::vector<double>
|
||||
get_array_double( const char *field ) const
|
||||
{
|
||||
int length;
|
||||
double *array;
|
||||
|
||||
if( vips_image_get_array_double( this->get_image(),
|
||||
field, &array, &length ) )
|
||||
throw( VError() );
|
||||
|
||||
std::vector<double> vector( array, array + length );
|
||||
|
||||
return( vector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a metadata item as a double.
|
||||
*
|
||||
|
@ -1724,7 +1781,7 @@ public:
|
|||
*
|
||||
* Rebuild with:
|
||||
*
|
||||
* make vips-operators.h
|
||||
* make vips-operators
|
||||
*
|
||||
* Then delete from here to the end of the class and paste in
|
||||
* vips-operators.h. We could just #include vips-operators.h, but
|
||||
|
@ -1732,7 +1789,7 @@ public:
|
|||
*/
|
||||
|
||||
// headers for vips operations
|
||||
// Wed 19 Aug 14:34:56 BST 2020
|
||||
// Wed Apr 21 06:00:31 PM CEST 2021
|
||||
// this file is generated automatically, do not edit!
|
||||
|
||||
/**
|
||||
|
@ -2679,6 +2736,22 @@ int find_trim( int *top, int *width, int *height, VOption *options = 0 ) const;
|
|||
*/
|
||||
static VImage fitsload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load fits from a source.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param source Source to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage fitsload_source( VSource source, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Save image to fits file.
|
||||
*
|
||||
|
@ -2789,6 +2862,7 @@ static VImage gaussmat( double sigma, double min_ampl, VOption *options = 0 );
|
|||
* **Optional parameters**
|
||||
* - **sigma** -- Standard deviation of pixels in generated image, double.
|
||||
* - **mean** -- Mean of pixels in generated image, double.
|
||||
* - **seed** -- Random number seed, int.
|
||||
*
|
||||
* @param width Image width in pixels.
|
||||
* @param height Image height in pixels.
|
||||
|
@ -2807,11 +2881,11 @@ static VImage gaussnoise( int width, int height, VOption *options = 0 );
|
|||
std::vector<double> getpoint( int x, int y, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Load gif with giflib.
|
||||
* Load gif with libnsgif.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **n** -- Load this many pages, int.
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
|
@ -2825,11 +2899,11 @@ std::vector<double> getpoint( int x, int y, VOption *options = 0 ) const;
|
|||
static VImage gifload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load gif with giflib.
|
||||
* Load gif with libnsgif.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **n** -- Load this many pages, int.
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
|
@ -2843,11 +2917,11 @@ static VImage gifload( const char *filename, VOption *options = 0 );
|
|||
static VImage gifload_buffer( VipsBlob *buffer, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load gif with giflib.
|
||||
* Load gif from source.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **n** -- Load this many pages, int.
|
||||
* - **page** -- Load this page from the file, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
|
@ -2977,13 +3051,13 @@ static VImage heifload_source( VSource source, VOption *options = 0 );
|
|||
* - **Q** -- Q factor, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **compression** -- Compression format, VipsForeignHeifCompression.
|
||||
* - **speed**: -- CPU effort, 0 slowest - 8 fastest, AV1 compression only, int.
|
||||
* - **speed** -- CPU effort, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
*
|
||||
* @param filename Filename to load from.
|
||||
* @param filename Filename to save to.
|
||||
* @param options Set of options.
|
||||
*/
|
||||
void heifsave( const char *filename, VOption *options = 0 ) const;
|
||||
|
@ -2995,7 +3069,7 @@ void heifsave( const char *filename, VOption *options = 0 ) const;
|
|||
* - **Q** -- Q factor, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **compression** -- Compression format, VipsForeignHeifCompression.
|
||||
* - **speed**: -- CPU effort, 0 slowest - 8 fastest, AV1 compression only, int.
|
||||
* - **speed** -- CPU effort, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
|
@ -3013,7 +3087,7 @@ VipsBlob *heifsave_buffer( VOption *options = 0 ) const;
|
|||
* - **Q** -- Q factor, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **compression** -- Compression format, VipsForeignHeifCompression.
|
||||
* - **speed**: -- CPU effort, 0 slowest - 8 fastest, AV1 compression only, int.
|
||||
* - **speed** -- CPU effort, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
|
@ -3156,6 +3230,7 @@ VImage hough_line( VOption *options = 0 ) const;
|
|||
* **Optional parameters**
|
||||
* - **pcs** -- Set Profile Connection Space, VipsPCS.
|
||||
* - **intent** -- Rendering intent, VipsIntent.
|
||||
* - **black_point_compensation** -- Enable black point compensation, bool.
|
||||
* - **output_profile** -- Filename to load output profile from, const char *.
|
||||
* - **depth** -- Output device space depth in bits, int.
|
||||
*
|
||||
|
@ -3170,6 +3245,7 @@ VImage icc_export( VOption *options = 0 ) const;
|
|||
* **Optional parameters**
|
||||
* - **pcs** -- Set Profile Connection Space, VipsPCS.
|
||||
* - **intent** -- Rendering intent, VipsIntent.
|
||||
* - **black_point_compensation** -- Enable black point compensation, bool.
|
||||
* - **embedded** -- Use embedded input profile, if available, bool.
|
||||
* - **input_profile** -- Filename to load input profile from, const char *.
|
||||
*
|
||||
|
@ -3184,6 +3260,7 @@ VImage icc_import( VOption *options = 0 ) const;
|
|||
* **Optional parameters**
|
||||
* - **pcs** -- Set Profile Connection Space, VipsPCS.
|
||||
* - **intent** -- Rendering intent, VipsIntent.
|
||||
* - **black_point_compensation** -- Enable black point compensation, bool.
|
||||
* - **embedded** -- Use embedded input profile, if available, bool.
|
||||
* - **input_profile** -- Filename to load input profile from, const char *.
|
||||
* - **depth** -- Output device space depth in bits, int.
|
||||
|
@ -3280,6 +3357,111 @@ VImage invfft( VOption *options = 0 ) const;
|
|||
*/
|
||||
VImage join( VImage in2, VipsDirection direction, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Load jpeg2000 image.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the image, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param filename Filename to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage jp2kload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load jpeg2000 image.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the image, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param buffer Buffer to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage jp2kload_buffer( VipsBlob *buffer, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load jpeg2000 image.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **page** -- Load this page from the image, int.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param source Source to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage jp2kload_source( VSource source, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Save image in heif format.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **tile_width** -- Tile width in pixels, int.
|
||||
* - **tile_height** -- Tile height in pixels, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **Q** -- Q factor, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
*
|
||||
* @param filename Filename to load from.
|
||||
* @param options Set of options.
|
||||
*/
|
||||
void jp2ksave( const char *filename, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Save image in heif format.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **tile_width** -- Tile width in pixels, int.
|
||||
* - **tile_height** -- Tile height in pixels, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **Q** -- Q factor, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
*
|
||||
* @param options Set of options.
|
||||
* @return Buffer to save to.
|
||||
*/
|
||||
VipsBlob *jp2ksave_buffer( VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Save image in heif format.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **tile_width** -- Tile width in pixels, int.
|
||||
* - **tile_height** -- Tile height in pixels, int.
|
||||
* - **lossless** -- Enable lossless compression, bool.
|
||||
* - **Q** -- Q factor, int.
|
||||
* - **subsample_mode** -- Select chroma subsample operation mode, VipsForeignSubsample.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
*
|
||||
* @param target Target to save to.
|
||||
* @param options Set of options.
|
||||
*/
|
||||
void jp2ksave_target( VTarget target, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Load jpeg from file.
|
||||
*
|
||||
|
@ -4030,7 +4212,7 @@ VImage msb( VOption *options = 0 ) const;
|
|||
VImage multiply( VImage right, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Load a nifti image.
|
||||
* Load nifti volume.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
|
@ -4045,6 +4227,22 @@ VImage multiply( VImage right, VOption *options = 0 ) const;
|
|||
*/
|
||||
static VImage niftiload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load nifti volumes.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param source Source to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage niftiload_source( VSource source, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Save image to nifti file.
|
||||
*
|
||||
|
@ -4078,7 +4276,7 @@ static VImage openexrload( const char *filename, VOption *options = 0 );
|
|||
* Load file with openslide.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **attach_associated** -- Attach all asssociated images, bool.
|
||||
* - **attach_associated** -- Attach all associated images, bool.
|
||||
* - **level** -- Load this level from the file, int.
|
||||
* - **autocrop** -- Crop to image bounds, bool.
|
||||
* - **associated** -- Load this associated image, const char *.
|
||||
|
@ -4094,6 +4292,26 @@ static VImage openexrload( const char *filename, VOption *options = 0 );
|
|||
*/
|
||||
static VImage openslideload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load source with openslide.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **attach_associated** -- Attach all associated images, bool.
|
||||
* - **level** -- Load this level from the file, int.
|
||||
* - **autocrop** -- Crop to image bounds, bool.
|
||||
* - **associated** -- Load this associated image, const char *.
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param source Source to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage openslideload_source( VSource source, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Load pdf from file.
|
||||
*
|
||||
|
@ -4171,6 +4389,7 @@ int percent( double percent, VOption *options = 0 ) const;
|
|||
* **Optional parameters**
|
||||
* - **cell_size** -- Size of Perlin cells, int.
|
||||
* - **uchar** -- Output an unsigned char image, bool.
|
||||
* - **seed** -- Random number seed, int.
|
||||
*
|
||||
* @param width Image width in pixels.
|
||||
* @param height Image height in pixels.
|
||||
|
@ -4339,7 +4558,7 @@ static VImage ppmload_source( VSource source, VOption *options = 0 );
|
|||
* **Optional parameters**
|
||||
* - **ascii** -- save as ascii, bool.
|
||||
* - **squash** -- save as one bit, bool.
|
||||
* - **bitdepth** -- Write as a 1 bit image, int.
|
||||
* - **bitdepth** -- set to 1 to write as a 1 bit image, int.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
|
@ -4355,7 +4574,7 @@ void ppmsave( const char *filename, VOption *options = 0 ) const;
|
|||
* **Optional parameters**
|
||||
* - **ascii** -- save as ascii, bool.
|
||||
* - **squash** -- save as one bit, bool.
|
||||
* - **bitdepth** -- Write as a 1 bit image, int.
|
||||
* - **bitdepth** -- set to 1 to write as a 1 bit image, int.
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
|
@ -5039,6 +5258,7 @@ static void system( const char *cmd_format, VOption *options = 0 );
|
|||
* - **width** -- Maximum image width in pixels, int.
|
||||
* - **height** -- Maximum image height in pixels, int.
|
||||
* - **align** -- Align on the low, centre or high edge, VipsAlign.
|
||||
* - **rgba** -- Enable RGBA output, bool.
|
||||
* - **dpi** -- DPI to render at, int.
|
||||
* - **justify** -- Justify lines, bool.
|
||||
* - **spacing** -- Line spacing, int.
|
||||
|
@ -5341,7 +5561,23 @@ VImage unpremultiply( VOption *options = 0 ) const;
|
|||
static VImage vipsload( const char *filename, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Save image to vips file.
|
||||
* Load vips from source.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **memory** -- Force open via memory, bool.
|
||||
* - **access** -- Required access pattern for this file, VipsAccess.
|
||||
* - **sequential** -- Sequential read only, bool.
|
||||
* - **fail** -- Fail on first error, bool.
|
||||
* - **disc** -- Open to disc, bool.
|
||||
*
|
||||
* @param source Source to load from.
|
||||
* @param options Set of options.
|
||||
* @return Output image.
|
||||
*/
|
||||
static VImage vipsload_source( VSource source, VOption *options = 0 );
|
||||
|
||||
/**
|
||||
* Save image to file in vips format.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
|
@ -5353,6 +5589,19 @@ static VImage vipsload( const char *filename, VOption *options = 0 );
|
|||
*/
|
||||
void vipssave( const char *filename, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Save image to target in vips format.
|
||||
*
|
||||
* **Optional parameters**
|
||||
* - **strip** -- Strip all metadata from image, bool.
|
||||
* - **background** -- Background value, std::vector<double>.
|
||||
* - **page_height** -- Set page height for multipage save, int.
|
||||
*
|
||||
* @param target Target to save to.
|
||||
* @param options Set of options.
|
||||
*/
|
||||
void vipssave_target( VTarget target, VOption *options = 0 ) const;
|
||||
|
||||
/**
|
||||
* Load webp from file.
|
||||
*
|
||||
|
@ -5490,6 +5739,7 @@ void webpsave_target( VTarget target, VOption *options = 0 ) const;
|
|||
*
|
||||
* **Optional parameters**
|
||||
* - **cell_size** -- Size of Worley cells, int.
|
||||
* - **seed** -- Random number seed, int.
|
||||
*
|
||||
* @param width Image width in pixels.
|
||||
* @param height Image height in pixels.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// bodies for vips operations
|
||||
// Mon 17 Aug 18:04:15 BST 2020
|
||||
// Wed Apr 21 06:00:31 PM CEST 2021
|
||||
// this file is generated automatically, do not edit!
|
||||
|
||||
VImage VImage::CMC2LCh( VOption *options ) const
|
||||
|
@ -1065,6 +1065,18 @@ VImage VImage::fitsload( const char *filename, VOption *options )
|
|||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::fitsload_source( VSource source, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "fitsload_source",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "source", source ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
void VImage::fitssave( const char *filename, VOption *options ) const
|
||||
{
|
||||
call( "fitssave",
|
||||
|
@ -1656,6 +1668,70 @@ VImage VImage::join( VImage in2, VipsDirection direction, VOption *options ) con
|
|||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::jp2kload( const char *filename, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "jp2kload",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "filename", filename ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::jp2kload_buffer( VipsBlob *buffer, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "jp2kload_buffer",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "buffer", buffer ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::jp2kload_source( VSource source, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "jp2kload_source",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "source", source ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
void VImage::jp2ksave( const char *filename, VOption *options ) const
|
||||
{
|
||||
call( "jp2ksave",
|
||||
(options ? options : VImage::option())->
|
||||
set( "in", *this )->
|
||||
set( "filename", filename ) );
|
||||
}
|
||||
|
||||
VipsBlob *VImage::jp2ksave_buffer( VOption *options ) const
|
||||
{
|
||||
VipsBlob *buffer;
|
||||
|
||||
call( "jp2ksave_buffer",
|
||||
(options ? options : VImage::option())->
|
||||
set( "in", *this )->
|
||||
set( "buffer", &buffer ) );
|
||||
|
||||
return( buffer );
|
||||
}
|
||||
|
||||
void VImage::jp2ksave_target( VTarget target, VOption *options ) const
|
||||
{
|
||||
call( "jp2ksave_target",
|
||||
(options ? options : VImage::option())->
|
||||
set( "in", *this )->
|
||||
set( "target", target ) );
|
||||
}
|
||||
|
||||
VImage VImage::jpegload( const char *filename, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
@ -2284,6 +2360,18 @@ VImage VImage::niftiload( const char *filename, VOption *options )
|
|||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::niftiload_source( VSource source, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "niftiload_source",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "source", source ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
void VImage::niftisave( const char *filename, VOption *options ) const
|
||||
{
|
||||
call( "niftisave",
|
||||
|
@ -2316,6 +2404,18 @@ VImage VImage::openslideload( const char *filename, VOption *options )
|
|||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::openslideload_source( VSource source, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "openslideload_source",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "source", source ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::pdfload( const char *filename, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
@ -3388,6 +3488,18 @@ VImage VImage::vipsload( const char *filename, VOption *options )
|
|||
return( out );
|
||||
}
|
||||
|
||||
VImage VImage::vipsload_source( VSource source, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
||||
call( "vipsload_source",
|
||||
(options ? options : VImage::option())->
|
||||
set( "out", &out )->
|
||||
set( "source", source ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
void VImage::vipssave( const char *filename, VOption *options ) const
|
||||
{
|
||||
call( "vipssave",
|
||||
|
@ -3396,6 +3508,14 @@ void VImage::vipssave( const char *filename, VOption *options ) const
|
|||
set( "filename", filename ) );
|
||||
}
|
||||
|
||||
void VImage::vipssave_target( VTarget target, VOption *options ) const
|
||||
{
|
||||
call( "vipssave_target",
|
||||
(options ? options : VImage::option())->
|
||||
set( "in", *this )->
|
||||
set( "target", target ) );
|
||||
}
|
||||
|
||||
VImage VImage::webpload( const char *filename, VOption *options )
|
||||
{
|
||||
VImage out;
|
||||
|
|
|
@ -61,7 +61,6 @@ EXTRA_HFILES=
|
|||
|
||||
IGNORE_VIPS_INCLUDE = \
|
||||
almostdeprecated.h \
|
||||
cimg_funcs.h \
|
||||
deprecated.h \
|
||||
vips7compat.h \
|
||||
dispatch.h \
|
||||
|
@ -127,7 +126,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">
|
||||
|
|
|
@ -496,6 +496,11 @@
|
|||
<entry>Load a fits image</entry>
|
||||
<entry>vips_fitsload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>fitsload_source</entry>
|
||||
<entry>Load fits from a source</entry>
|
||||
<entry>vips_fitsload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>fitssave</entry>
|
||||
<entry>Save image to fits file</entry>
|
||||
|
@ -558,17 +563,17 @@
|
|||
</row>
|
||||
<row>
|
||||
<entry>gifload</entry>
|
||||
<entry>Load gif with giflib</entry>
|
||||
<entry>Load gif with libnsgif</entry>
|
||||
<entry>vips_gifload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>gifload_buffer</entry>
|
||||
<entry>Load gif with giflib</entry>
|
||||
<entry>Load gif with libnsgif</entry>
|
||||
<entry>vips_gifload_buffer()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>gifload_source</entry>
|
||||
<entry>Load gif with giflib</entry>
|
||||
<entry>Load gif from source</entry>
|
||||
<entry>vips_gifload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
@ -736,6 +741,36 @@
|
|||
<entry>Join a pair of images</entry>
|
||||
<entry>vips_join()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2kload</entry>
|
||||
<entry>Load jpeg2000 image</entry>
|
||||
<entry>vips_jp2kload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2kload_buffer</entry>
|
||||
<entry>Load jpeg2000 image</entry>
|
||||
<entry>vips_jp2kload_buffer()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2kload_source</entry>
|
||||
<entry>Load jpeg2000 image</entry>
|
||||
<entry>vips_jp2kload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2ksave</entry>
|
||||
<entry>Save image in heif format</entry>
|
||||
<entry>vips_jp2ksave()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2ksave_buffer</entry>
|
||||
<entry>Save image in heif format</entry>
|
||||
<entry>vips_jp2ksave_buffer()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jp2ksave_target</entry>
|
||||
<entry>Save image in heif format</entry>
|
||||
<entry>vips_jp2ksave_target()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>jpegload</entry>
|
||||
<entry>Load jpeg from file</entry>
|
||||
|
@ -973,9 +1008,14 @@
|
|||
</row>
|
||||
<row>
|
||||
<entry>niftiload</entry>
|
||||
<entry>Load a nifti image</entry>
|
||||
<entry>Load nifti volume</entry>
|
||||
<entry>vips_niftiload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>niftiload_source</entry>
|
||||
<entry>Load nifti volumes</entry>
|
||||
<entry>vips_niftiload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>niftisave</entry>
|
||||
<entry>Save image to nifti file</entry>
|
||||
|
@ -991,6 +1031,11 @@
|
|||
<entry>Load file with openslide</entry>
|
||||
<entry>vips_openslideload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>openslideload_source</entry>
|
||||
<entry>Load source with openslide</entry>
|
||||
<entry>vips_openslideload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pdfload</entry>
|
||||
<entry>Load pdf from file</entry>
|
||||
|
@ -1056,11 +1101,21 @@
|
|||
<entry>Load ppm from file</entry>
|
||||
<entry>vips_ppmload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ppmload_source</entry>
|
||||
<entry>Load ppm base class</entry>
|
||||
<entry>vips_ppmload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ppmsave</entry>
|
||||
<entry>Save image to ppm file</entry>
|
||||
<entry>vips_ppmsave()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ppmsave_target</entry>
|
||||
<entry>Save to ppm</entry>
|
||||
<entry>vips_ppmsave_target()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>premultiply</entry>
|
||||
<entry>Premultiply image alpha</entry>
|
||||
|
@ -1426,11 +1481,21 @@
|
|||
<entry>Load vips from file</entry>
|
||||
<entry>vips_vipsload()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>vipsload_source</entry>
|
||||
<entry>Load vips from source</entry>
|
||||
<entry>vips_vipsload_source()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>vipssave</entry>
|
||||
<entry>Save image to vips file</entry>
|
||||
<entry>Save image to file in vips format</entry>
|
||||
<entry>vips_vipssave()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>vipssave_target</entry>
|
||||
<entry>Save image to target in vips format</entry>
|
||||
<entry>vips_vipssave_target()</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>webpload</entry>
|
||||
<entry>Load webp from file</entry>
|
||||
|
|
|
@ -9,6 +9,10 @@ else
|
|||
OPTIONAL_DIST_DIR += deprecated
|
||||
endif
|
||||
|
||||
if ENABLE_NSGIF
|
||||
OPTIONAL_LIB += foreign/libnsgif/libnsgif.la
|
||||
endif
|
||||
|
||||
SUBDIRS = \
|
||||
include \
|
||||
foreign \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
noinst_LTLIBRARIES = libcolour.la
|
||||
|
||||
SUBDIRS = profiles
|
||||
|
||||
noinst_LTLIBRARIES = libcolour.la
|
||||
|
||||
libcolour_la_SOURCES = \
|
||||
profiles.c \
|
||||
profiles.h \
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
* they can be triggered under normal circumstances
|
||||
* 17/4/19 kleisauke
|
||||
* - better rejection of broken embedded profiles
|
||||
* 29/3/21 [hanssonrickard]
|
||||
* - add black_point_compensation
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -155,6 +157,7 @@ typedef struct _VipsIcc {
|
|||
VipsIntent intent;
|
||||
VipsPCS pcs;
|
||||
int depth;
|
||||
gboolean black_point_compensation;
|
||||
|
||||
VipsBlob *in_blob;
|
||||
cmsHPROFILE in_profile;
|
||||
|
@ -218,6 +221,8 @@ vips_icc_build( VipsObject *object )
|
|||
VipsColourCode *code = (VipsColourCode *) object;
|
||||
VipsIcc *icc = (VipsIcc *) object;
|
||||
|
||||
cmsUInt32Number flags;
|
||||
|
||||
if( icc->depth != 8 &&
|
||||
icc->depth != 16 ) {
|
||||
vips_error( class->nickname,
|
||||
|
@ -356,10 +361,15 @@ vips_icc_build( VipsObject *object )
|
|||
/* Use cmsFLAGS_NOCACHE to disable the 1-pixel cache and make
|
||||
* calling cmsDoTransform() from multiple threads safe.
|
||||
*/
|
||||
flags = cmsFLAGS_NOCACHE;
|
||||
|
||||
if( icc->black_point_compensation )
|
||||
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
|
||||
|
||||
if( !(icc->trans = cmsCreateTransform(
|
||||
icc->in_profile, icc->in_icc_format,
|
||||
icc->out_profile, icc->out_icc_format,
|
||||
icc->intent, cmsFLAGS_NOCACHE )) )
|
||||
icc->intent, flags )) )
|
||||
return( -1 );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_icc_parent_class )->
|
||||
|
@ -780,6 +790,13 @@ vips_icc_class_init( VipsIccClass *class )
|
|||
G_STRUCT_OFFSET( VipsIcc, pcs ),
|
||||
VIPS_TYPE_PCS, VIPS_PCS_LAB );
|
||||
|
||||
VIPS_ARG_BOOL( class, "black_point_compensation", 7,
|
||||
_( "Black point compensation" ),
|
||||
_( "Enable black point compensation" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsIcc, black_point_compensation ),
|
||||
FALSE );
|
||||
|
||||
cmsSetLogErrorHandler( icc_error );
|
||||
}
|
||||
|
||||
|
@ -1411,10 +1428,11 @@ vips_icc_is_compatible_profile( VipsImage *image,
|
|||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @input_profile: get the input profile from here
|
||||
* * @intent: transform with this intent
|
||||
* * @embedded: use profile embedded in input image
|
||||
* * @pcs: use XYZ or LAB PCS
|
||||
* * @pcs: #VipsPCS, use XYZ or LAB PCS
|
||||
* * @intent: #VipsIntent, transform with this intent
|
||||
* * @black_point_compensation: %gboolean, enable black point compensation
|
||||
* * @embedded: %gboolean, use profile embedded in input image
|
||||
* * @input_profile: %gchararray, get the input profile from here
|
||||
*
|
||||
* Import an image from device space to D65 LAB with an ICC profile. If @pcs is
|
||||
* set to #VIPS_PCS_XYZ, use CIE XYZ PCS instead.
|
||||
|
@ -1431,6 +1449,9 @@ vips_icc_is_compatible_profile( VipsImage *image,
|
|||
* @input_profile. If @input_profile is not supplied, the
|
||||
* metadata profile, if any, is used as a fall-back.
|
||||
*
|
||||
* If @black_point_compensation is set, LCMS black point compensation is
|
||||
* enabled.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
|
@ -1454,10 +1475,11 @@ vips_icc_import( VipsImage *in, VipsImage **out, ... )
|
|||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @intent: transform with this intent
|
||||
* * @depth: depth of output image in bits
|
||||
* * @output_profile: get the output profile from here
|
||||
* * @pcs: use XYZ or LAB PCS
|
||||
* * @pcs: #VipsPCS, use XYZ or LAB PCS
|
||||
* * @intent: #VipsIntent, transform with this intent
|
||||
* * @black_point_compensation: %gboolean, enable black point compensation
|
||||
* * @output_profile: %gchararray, get the output profile from here
|
||||
* * @depth: %gint, depth of output image in bits
|
||||
*
|
||||
* Export an image from D65 LAB to device space with an ICC profile.
|
||||
* If @pcs is
|
||||
|
@ -1466,6 +1488,9 @@ vips_icc_import( VipsImage *in, VipsImage **out, ... )
|
|||
* If @output_profile is set, export with that and attach it to the output
|
||||
* image.
|
||||
*
|
||||
* If @black_point_compensation is set, LCMS black point compensation is
|
||||
* enabled.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
|
@ -1490,10 +1515,12 @@ vips_icc_export( VipsImage *in, VipsImage **out, ... )
|
|||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @input_profile: get the input profile from here
|
||||
* * @intent: transform with this intent
|
||||
* * @depth: depth of output image in bits
|
||||
* * @embedded: use profile embedded in input image
|
||||
* * @pcs: #VipsPCS, use XYZ or LAB PCS
|
||||
* * @intent: #VipsIntent, transform with this intent
|
||||
* * @black_point_compensation: %gboolean, enable black point compensation
|
||||
* * @embedded: %gboolean, use profile embedded in input image
|
||||
* * @input_profile: %gchararray, get the input profile from here
|
||||
* * @depth: %gint, depth of output image in bits
|
||||
*
|
||||
* Transform an image with a pair of ICC profiles. The input image is moved to
|
||||
* profile-connection space with the input profile and then to the output
|
||||
|
@ -1511,6 +1538,9 @@ vips_icc_export( VipsImage *in, VipsImage **out, ... )
|
|||
* @input_profile. If @input_profile is not supplied, the
|
||||
* metadata profile, if any, is used as a fall-back.
|
||||
*
|
||||
* If @black_point_compensation is set, LCMS black point compensation is
|
||||
* enabled.
|
||||
*
|
||||
* The output image has the output profile attached to the #VIPS_META_ICC_NAME
|
||||
* field.
|
||||
*
|
||||
|
|
|
@ -32143,6 +32143,64 @@ static VipsProfileFallback vips__profile_fallback_cmyk = {
|
|||
}
|
||||
};
|
||||
|
||||
static VipsProfileFallback vips__profile_fallback_p3 = {
|
||||
"p3",
|
||||
736,
|
||||
{
|
||||
0x78, 0xDA, 0x7D, 0xD0, 0x03, 0xA0, 0xE4, 0x30, 0x14, 0x05, 0xD0, 0x57,
|
||||
0x7C, 0xDB, 0xB6, 0x6D, 0xDB, 0xB6, 0x8D, 0xB1, 0xD1, 0xCE, 0xDA, 0xB6,
|
||||
0x6D, 0xDB, 0xB6, 0x6D, 0xDB, 0xB6, 0xED, 0x74, 0xED, 0x5B, 0x9D, 0xC6,
|
||||
0x09, 0x00, 0x7E, 0x49, 0xCC, 0x92, 0x50, 0xB8, 0x21, 0x80, 0x44, 0x4A,
|
||||
0x2B, 0x8B, 0x33, 0x92, 0x1D, 0x2B, 0xAB, 0xAA, 0x1D, 0x35, 0xAE, 0x00,
|
||||
0x01, 0xA6, 0xA0, 0x05, 0xFA, 0x60, 0xD7, 0xC4, 0xA2, 0xE4, 0x79, 0x25,
|
||||
0xE9, 0xA5, 0x80, 0x42, 0x35, 0xB5, 0xA4, 0x58, 0xB4, 0x52, 0x0C, 0xBF,
|
||||
0xE4, 0xC5, 0x09, 0xC0, 0x98, 0xEF, 0x51, 0x3F, 0x7E, 0x93, 0x94, 0xDD,
|
||||
0x56, 0x66, 0xB0, 0xF7, 0x52, 0x5A, 0x52, 0x78, 0x42, 0x41, 0x6A, 0xD8,
|
||||
0x5E, 0xEB, 0x1E, 0x56, 0xF0, 0xFF, 0x68, 0xB1, 0x39, 0x14, 0x0B, 0x7D,
|
||||
0x1F, 0xA1, 0xA7, 0x9E, 0x25, 0x57, 0xD2, 0x00, 0x98, 0x2E, 0xB2, 0x6E,
|
||||
0x4B, 0x5A, 0xCE, 0xD8, 0x12, 0xD9, 0x54, 0x89, 0x16, 0x85, 0xEC, 0xCB,
|
||||
0x98, 0xF7, 0xC5, 0x89, 0x8C, 0x9B, 0xBF, 0xB8, 0x94, 0xB1, 0xB2, 0xB4,
|
||||
0x38, 0x05, 0x99, 0x8F, 0x9E, 0x56, 0xBC, 0x9F, 0xDC, 0xFC, 0x93, 0xBF,
|
||||
0xCE, 0xC5, 0x44, 0x8D, 0x2A, 0x0C, 0x41, 0xE5, 0x3F, 0x42, 0x73, 0x5A,
|
||||
0xD1, 0xCC, 0x37, 0x25, 0x25, 0x10, 0x98, 0x33, 0xF8, 0x52, 0xFA, 0xB4,
|
||||
0x08, 0x30, 0xF4, 0xC1, 0xCC, 0xF7, 0xFD, 0x28, 0xEB, 0x7A, 0x11, 0x20,
|
||||
0x6E, 0x23, 0xA3, 0x1F, 0x65, 0xD9, 0xE8, 0x7F, 0x71, 0x04, 0x80, 0xF6,
|
||||
0xF2, 0x1F, 0x65, 0x9E, 0x91, 0x00, 0x46, 0xDA, 0x00, 0xBB, 0x5A, 0xB1,
|
||||
0x54, 0xCA, 0x16, 0xF0, 0x25, 0x2B, 0xD0, 0x63, 0x0B, 0x91, 0x50, 0x0A,
|
||||
0x72, 0xE8, 0x07, 0xB3, 0x60, 0x1B, 0x5C, 0xC6, 0x00, 0x73, 0xC6, 0xD2,
|
||||
0x31, 0x09, 0x36, 0x1C, 0xDB, 0x8C, 0x3D, 0xC2, 0x1D, 0xF1, 0x32, 0xBC,
|
||||
0x2F, 0xBE, 0x8D, 0xC0, 0x88, 0x04, 0xA2, 0x0B, 0xB1, 0x83, 0xD4, 0x27,
|
||||
0xAB, 0xC8, 0x99, 0xE4, 0x6B, 0xB5, 0x5C, 0xB5, 0x69, 0x6A, 0x1F, 0xD4,
|
||||
0x6B, 0xD5, 0x37, 0x68, 0x38, 0x69, 0xF4, 0xD1, 0x78, 0xA6, 0xC9, 0xD2,
|
||||
0x3C, 0xAE, 0x95, 0xA5, 0xB5, 0x55, 0x3B, 0x41, 0x7B, 0xA3, 0x4E, 0xB2,
|
||||
0xCE, 0x6E, 0xDD, 0x52, 0xDD, 0xCB, 0x7A, 0xB4, 0xBE, 0x96, 0xFE, 0x14,
|
||||
0x83, 0x44, 0x83, 0x4B, 0x86, 0xDD, 0x8D, 0xFC, 0x8C, 0xCE, 0x18, 0xF7,
|
||||
0x31, 0x89, 0x37, 0x79, 0x61, 0xBA, 0xC4, 0x4C, 0x61, 0x1E, 0x6E, 0xFE,
|
||||
0xDE, 0x62, 0x8F, 0xE5, 0x68, 0x2B, 0xA9, 0x75, 0xBA, 0x8D, 0xB3, 0x2D,
|
||||
0x61, 0x7B, 0xD3, 0xEE, 0x90, 0xFD, 0x7A, 0x87, 0x05, 0x8E, 0xD3, 0x9C,
|
||||
0x26, 0x38, 0x8F, 0x73, 0x99, 0xE8, 0x3A, 0xDD, 0x6D, 0xB1, 0xFB, 0x26,
|
||||
0x8F, 0xE3, 0x9E, 0xF7, 0xBD, 0xB5, 0x7D, 0x7C, 0x7C, 0x8B, 0xFC, 0xDA,
|
||||
0xF9, 0xCF, 0x09, 0xB8, 0x10, 0x64, 0x1E, 0x5C, 0x1C, 0x32, 0x2C, 0xF4,
|
||||
0x74, 0xB8, 0x6B, 0x04, 0x15, 0xB9, 0x23, 0xDA, 0x31, 0xA6, 0x5D, 0xEC,
|
||||
0xC5, 0xF8, 0xB4, 0x84, 0x45, 0x49, 0x4E, 0xC9, 0x23, 0x52, 0x0D, 0xD3,
|
||||
0x06, 0x66, 0x18, 0x67, 0x8E, 0xCD, 0xF6, 0xCC, 0x59, 0x9B, 0x57, 0x94,
|
||||
0xFF, 0xA0, 0x70, 0x60, 0x71, 0x58, 0xC9, 0xA5, 0xB2, 0x41, 0x15, 0x69,
|
||||
0x55, 0x50, 0xBD, 0xA1, 0xB6, 0x5B, 0x7D, 0x6E, 0xA3, 0x4D, 0xD3, 0x43,
|
||||
0xD6, 0x4E, 0xCE, 0x0C, 0x5E, 0x6F, 0x81, 0x42, 0xD4, 0x20, 0x29, 0x92,
|
||||
0x65, 0x2B, 0xD2, 0xA9, 0x6C, 0x55, 0x51, 0xCB, 0xFA, 0xD6, 0x8A, 0xB6,
|
||||
0xBD, 0xDA, 0xCF, 0xE8, 0xB8, 0xAB, 0xF3, 0xA3, 0x6E, 0xF6, 0x3D, 0x0A,
|
||||
0x7B, 0xF5, 0xEE, 0xB3, 0xBD, 0xBF, 0xD6, 0xC0, 0xA2, 0xC1, 0x13, 0x87,
|
||||
0x3E, 0x1D, 0x91, 0x33, 0x6A, 0xEE, 0x58, 0xFD, 0xF1, 0xAD, 0x26, 0xDE,
|
||||
0x9C, 0x52, 0x33, 0xED, 0xC4, 0xCC, 0xF2, 0xD9, 0x67, 0xE7, 0xF1, 0x16,
|
||||
0xBC, 0x5C, 0x3C, 0x70, 0x99, 0xF7, 0x8A, 0x7D, 0xAB, 0xE9, 0x75, 0x4E,
|
||||
0x1B, 0x8E, 0x6F, 0xEE, 0xBF, 0x2D, 0x77, 0xA7, 0xE1, 0xEE, 0x33, 0xFB,
|
||||
0xE6, 0x1E, 0xEC, 0x78, 0xA4, 0xF6, 0x78, 0xDC, 0x29, 0xD7, 0xB3, 0xC6,
|
||||
0x17, 0xC8, 0x4B, 0x1F, 0xAE, 0xBE, 0xBB, 0x89, 0xDD, 0xD1, 0xBD, 0x6F,
|
||||
0xFB, 0x28, 0xF4, 0x69, 0xE1, 0x0B, 0xEA, 0xF5, 0xD8, 0x77, 0x7B, 0x3E,
|
||||
0x7E, 0xFC, 0x04, 0xD4, 0xCA, 0xD2, 0x46,
|
||||
}
|
||||
};
|
||||
|
||||
static VipsProfileFallback vips__profile_fallback_sRGB = {
|
||||
"sRGB",
|
||||
6922,
|
||||
|
@ -32348,6 +32406,7 @@ static VipsProfileFallback vips__profile_fallback_sRGB = {
|
|||
|
||||
VipsProfileFallback *vips__profile_fallback_table[] = {
|
||||
&vips__profile_fallback_cmyk,
|
||||
&vips__profile_fallback_p3,
|
||||
&vips__profile_fallback_sRGB,
|
||||
NULL
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
EXTRA_DIST = \
|
||||
p3.icm \
|
||||
cmyk.icm \
|
||||
sRGB.icm
|
||||
|
|
Binary file not shown.
|
@ -55,13 +55,17 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
#include <cstdlib>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#if defined(HAVE__ALIGNED_MALLOC) || defined(HAVE_MEMALIGN)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
@ -81,7 +85,7 @@
|
|||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* A vector of four floats.
|
||||
*/
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float))));
|
||||
typedef float v4f __attribute__((vector_size(4 * sizeof(float)),aligned(16)));
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
typedef struct _VipsCompositeBase {
|
||||
|
@ -130,12 +134,6 @@ typedef struct _VipsCompositeBase {
|
|||
*/
|
||||
gboolean skippable;
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* max_band as a vector, for the RGBA case.
|
||||
*/
|
||||
v4f max_band_vec;
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
} VipsCompositeBase;
|
||||
|
||||
typedef VipsConversionClass VipsCompositeBaseClass;
|
||||
|
@ -168,6 +166,14 @@ vips_composite_base_dispose( GObject *gobject )
|
|||
/* Our sequence value.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* max_band as a vector, for the RGBA case. This must be
|
||||
* defined first to ensure that the member is aligned
|
||||
* on a 16-byte boundary.
|
||||
*/
|
||||
v4f max_band_vec;
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
VipsCompositeBase *composite;
|
||||
|
||||
/* Full set of input regions, each made on the corresponding input
|
||||
|
@ -196,6 +202,39 @@ typedef struct {
|
|||
|
||||
} VipsCompositeSequence;
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* Allocate aligned memory. The return value can be released
|
||||
* by calling the vips_free_aligned() function, for example:
|
||||
* VIPS_FREEF( vips_free_aligned, ptr );
|
||||
*/
|
||||
static inline void *
|
||||
vips_alloc_aligned( size_t sz, size_t align )
|
||||
{
|
||||
g_assert( !(align & (align - 1)) );
|
||||
#ifdef HAVE__ALIGNED_MALLOC
|
||||
return _aligned_malloc( sz, align );
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
void *ptr;
|
||||
if( posix_memalign( &ptr, align, sz ) ) return NULL;
|
||||
return ptr;
|
||||
#elif defined(HAVE_MEMALIGN)
|
||||
return memalign( align, sz );
|
||||
#else
|
||||
#error Missing aligned alloc implementation
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
vips_free_aligned( void* ptr )
|
||||
{
|
||||
#ifdef HAVE__ALIGNED_MALLOC
|
||||
_aligned_free( ptr );
|
||||
#else /*defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)*/
|
||||
free( ptr );
|
||||
#endif
|
||||
}
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
static int
|
||||
vips_composite_stop( void *vseq, void *a, void *b )
|
||||
{
|
||||
|
@ -216,7 +255,11 @@ vips_composite_stop( void *vseq, void *a, void *b )
|
|||
VIPS_FREE( seq->enabled );
|
||||
VIPS_FREE( seq->p );
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
VIPS_FREEF( vips_free_aligned, seq );
|
||||
#else /*!defined(HAVE_VECTOR_ARITH)*/
|
||||
VIPS_FREE( seq );
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -230,7 +273,14 @@ vips_composite_start( VipsImage *out, void *a, void *b )
|
|||
VipsCompositeSequence *seq;
|
||||
int i, n;
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* Ensure that the memory is aligned on a 16-byte boundary.
|
||||
*/
|
||||
if( !(seq = ((VipsCompositeSequence *) vips_alloc_aligned(
|
||||
sizeof( VipsCompositeSequence ), 16 ))) )
|
||||
#else /*!defined(HAVE_VECTOR_ARITH)*/
|
||||
if( !(seq = VIPS_NEW( NULL, VipsCompositeSequence )) )
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
return( NULL );
|
||||
|
||||
seq->composite = composite;
|
||||
|
@ -280,7 +330,19 @@ vips_composite_start( VipsImage *out, void *a, void *b )
|
|||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* We need a float version for the vector path.
|
||||
*/
|
||||
if( composite->bands == 3 )
|
||||
seq->max_band_vec = (v4f){
|
||||
(float) composite->max_band[0],
|
||||
(float) composite->max_band[1],
|
||||
(float) composite->max_band[2],
|
||||
(float) composite->max_band[3]
|
||||
};
|
||||
#endif
|
||||
|
||||
return( seq );
|
||||
}
|
||||
|
||||
|
@ -664,9 +726,11 @@ vips_composite_base_blend( VipsCompositeBase *composite,
|
|||
*/
|
||||
template <typename T>
|
||||
static void
|
||||
vips_composite_base_blend3( VipsCompositeBase *composite,
|
||||
vips_composite_base_blend3( VipsCompositeSequence *seq,
|
||||
VipsBlendMode mode, v4f &B, T * restrict p )
|
||||
{
|
||||
VipsCompositeBase *composite = seq->composite;
|
||||
|
||||
v4f A;
|
||||
float aA;
|
||||
float aB;
|
||||
|
@ -684,7 +748,7 @@ vips_composite_base_blend3( VipsCompositeBase *composite,
|
|||
A[2] = p[2];
|
||||
A[3] = p[3];
|
||||
|
||||
A /= composite->max_band_vec;
|
||||
A /= seq->max_band_vec;
|
||||
|
||||
aA = A[3];
|
||||
aB = B[3];
|
||||
|
@ -975,7 +1039,7 @@ vips_combine_pixels3( VipsCompositeSequence *seq, VipsPel *q )
|
|||
|
||||
/* Scale the base pixel to 0 - 1.
|
||||
*/
|
||||
B /= composite->max_band_vec;
|
||||
B /= seq->max_band_vec;
|
||||
aB = B[3];
|
||||
|
||||
if( !composite->premultiplied ) {
|
||||
|
@ -987,7 +1051,7 @@ vips_combine_pixels3( VipsCompositeSequence *seq, VipsPel *q )
|
|||
int j = seq->enabled[i];
|
||||
VipsBlendMode m = n_mode == 1 ? mode[0] : mode[j - 1];
|
||||
|
||||
vips_composite_base_blend3<T>( composite, m, B, tp[i] );
|
||||
vips_composite_base_blend3<T>( seq, m, B, tp[i] );
|
||||
}
|
||||
|
||||
/* Unpremultiply, if necessary.
|
||||
|
@ -1006,7 +1070,7 @@ vips_combine_pixels3( VipsCompositeSequence *seq, VipsPel *q )
|
|||
|
||||
/* Write back as a full range pixel, clipping to range.
|
||||
*/
|
||||
B *= composite->max_band_vec;
|
||||
B *= seq->max_band_vec;
|
||||
if( min_T != 0 ||
|
||||
max_T != 0 ) {
|
||||
float low = min_T;
|
||||
|
@ -1386,14 +1450,6 @@ vips_composite_base_build( VipsObject *object )
|
|||
return( -1 );
|
||||
}
|
||||
|
||||
#ifdef HAVE_VECTOR_ARITH
|
||||
/* We need a float version for the vector path.
|
||||
*/
|
||||
if( composite->bands == 3 )
|
||||
for( int b = 0; b <= 3; b++ )
|
||||
composite->max_band_vec[b] = composite->max_band[b];
|
||||
#endif /*HAVE_VECTOR_ARITH*/
|
||||
|
||||
/* Transform the input images to match in format. We may have
|
||||
* mixed float and double, for example.
|
||||
*/
|
||||
|
|
|
@ -116,9 +116,9 @@ vips_create_operation_init( void )
|
|||
extern GType vips_gaussmat_get_type( void );
|
||||
extern GType vips_logmat_get_type( void );
|
||||
extern GType vips_gaussnoise_get_type( void );
|
||||
#ifdef HAVE_PANGOFT2
|
||||
#ifdef HAVE_PANGOCAIRO
|
||||
extern GType vips_text_get_type( void );
|
||||
#endif /*HAVE_PANGOFT2*/
|
||||
#endif /*HAVE_PANGOCAIRO*/
|
||||
extern GType vips_xyz_get_type( void );
|
||||
extern GType vips_eye_get_type( void );
|
||||
extern GType vips_grey_get_type( void );
|
||||
|
@ -146,9 +146,9 @@ vips_create_operation_init( void )
|
|||
vips_gaussmat_get_type();
|
||||
vips_logmat_get_type();
|
||||
vips_gaussnoise_get_type();
|
||||
#ifdef HAVE_PANGOFT2
|
||||
#ifdef HAVE_PANGOCAIRO
|
||||
vips_text_get_type();
|
||||
#endif /*HAVE_PANGOFT2*/
|
||||
#endif /*HAVE_PANGOCAIRO*/
|
||||
vips_xyz_get_type();
|
||||
vips_eye_get_type();
|
||||
vips_grey_get_type();
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
* - fitting could occasionally terminate early [levmorozov]
|
||||
* 16/5/20 [keiviv]
|
||||
* - don't add fontfiles repeatedly
|
||||
* 12/4/21
|
||||
* - switch to cairo for text rendering
|
||||
* - add rgba flag
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -74,11 +77,17 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#ifdef HAVE_PANGOFT2
|
||||
#ifdef HAVE_PANGOCAIRO
|
||||
|
||||
#include <cairo.h>
|
||||
#include <pango/pango.h>
|
||||
#include <pango/pangoft2.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#ifdef HAVE_FONTCONFIG
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#endif
|
||||
|
||||
#include "pcreate.h"
|
||||
|
||||
|
@ -94,8 +103,8 @@ typedef struct _VipsText {
|
|||
gboolean justify;
|
||||
int dpi;
|
||||
char *fontfile;
|
||||
gboolean rgba;
|
||||
|
||||
FT_Bitmap bitmap;
|
||||
PangoContext *context;
|
||||
PangoLayout *layout;
|
||||
|
||||
|
@ -129,7 +138,6 @@ vips_text_dispose( GObject *gobject )
|
|||
|
||||
VIPS_UNREF( text->layout );
|
||||
VIPS_UNREF( text->context );
|
||||
VIPS_FREE( text->bitmap.buffer );
|
||||
|
||||
G_OBJECT_CLASS( vips_text_parent_class )->dispose( gobject );
|
||||
}
|
||||
|
@ -186,8 +194,8 @@ vips_text_get_extents( VipsText *text, VipsRect *extents )
|
|||
PangoRectangle ink_rect;
|
||||
PangoRectangle logical_rect;
|
||||
|
||||
pango_ft2_font_map_set_resolution(
|
||||
PANGO_FT2_FONT_MAP( vips_text_fontmap ), text->dpi, text->dpi );
|
||||
pango_cairo_font_map_set_resolution(
|
||||
PANGO_CAIRO_FONT_MAP( vips_text_fontmap ), text->dpi );
|
||||
|
||||
VIPS_UNREF( text->layout );
|
||||
if( !(text->layout = text_layout_new( text->context,
|
||||
|
@ -340,9 +348,12 @@ vips_text_build( VipsObject *object )
|
|||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsCreate *create = VIPS_CREATE( object );
|
||||
VipsText *text = (VipsText *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 );
|
||||
|
||||
VipsRect extents;
|
||||
int y;
|
||||
VipsImage *image;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_text_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
@ -356,7 +367,8 @@ vips_text_build( VipsObject *object )
|
|||
g_mutex_lock( vips_text_lock );
|
||||
|
||||
if( !vips_text_fontmap )
|
||||
vips_text_fontmap = pango_ft2_font_map_new();
|
||||
vips_text_fontmap = pango_cairo_font_map_new();
|
||||
|
||||
if( !vips_text_fontfiles )
|
||||
vips_text_fontfiles =
|
||||
g_hash_table_new( g_str_hash, g_str_equal );
|
||||
|
@ -364,20 +376,25 @@ vips_text_build( VipsObject *object )
|
|||
text->context = pango_font_map_create_context(
|
||||
PANGO_FONT_MAP( vips_text_fontmap ) );
|
||||
|
||||
#ifdef HAVE_FONTCONFIG
|
||||
if( text->fontfile &&
|
||||
!g_hash_table_lookup( vips_text_fontfiles, text->fontfile ) ) {
|
||||
/* This can fail if you eg. add the same font from two
|
||||
* different files. Just warn.
|
||||
*/
|
||||
if( !FcConfigAppFontAddFile( NULL,
|
||||
(const FcChar8 *) text->fontfile ) ) {
|
||||
vips_error( class->nickname,
|
||||
_( "unable to load font \"%s\"" ),
|
||||
(const FcChar8 *) text->fontfile ) )
|
||||
g_warning( _( "unable to load fontfile \"%s\"" ),
|
||||
text->fontfile );
|
||||
g_mutex_unlock( vips_text_lock );
|
||||
return( -1 );
|
||||
}
|
||||
g_hash_table_insert( vips_text_fontfiles,
|
||||
text->fontfile,
|
||||
g_strdup( text->fontfile ) );
|
||||
}
|
||||
#else /*!HAVE_FONTCONFIG*/
|
||||
if( text->fontfile )
|
||||
g_warning( "%s",
|
||||
_( "ignoring fontfile (no fontconfig support)" ) );
|
||||
#endif /*HAVE_FONTCONFIG*/
|
||||
|
||||
/* If our caller set height and not dpi, we adjust dpi until
|
||||
* we get a fit.
|
||||
|
@ -399,40 +416,65 @@ vips_text_build( VipsObject *object )
|
|||
return( -1 );
|
||||
}
|
||||
|
||||
text->bitmap.width = extents.width;
|
||||
text->bitmap.pitch = (text->bitmap.width + 3) & ~3;
|
||||
text->bitmap.rows = extents.height;
|
||||
if( !(text->bitmap.buffer =
|
||||
VIPS_ARRAY( NULL,
|
||||
text->bitmap.pitch * text->bitmap.rows, VipsPel )) ) {
|
||||
/* Set DPI as pixels/mm.
|
||||
*/
|
||||
image = t[0] = vips_image_new_memory();
|
||||
vips_image_init_fields( image,
|
||||
extents.width, extents.height, 4,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_sRGB,
|
||||
text->dpi / 25.4, text->dpi / 25.4 );
|
||||
|
||||
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
image->Xoffset = extents.left;
|
||||
image->Yoffset = extents.top;
|
||||
|
||||
if( vips_image_write_prepare( image ) ) {
|
||||
g_mutex_unlock( vips_text_lock );
|
||||
return( -1 );
|
||||
}
|
||||
text->bitmap.num_grays = 256;
|
||||
text->bitmap.pixel_mode = ft_pixel_mode_grays;
|
||||
memset( text->bitmap.buffer, 0x00,
|
||||
text->bitmap.pitch * text->bitmap.rows );
|
||||
|
||||
pango_ft2_render_layout( &text->bitmap, text->layout,
|
||||
-extents.left, -extents.top );
|
||||
surface = cairo_image_surface_create_for_data(
|
||||
VIPS_IMAGE_ADDR( image, 0, 0 ),
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
image->Xsize, image->Ysize,
|
||||
VIPS_IMAGE_SIZEOF_LINE( image ) );
|
||||
cr = cairo_create( surface );
|
||||
cairo_surface_destroy( surface );
|
||||
|
||||
cairo_translate( cr, -extents.left, -extents.top );
|
||||
|
||||
pango_cairo_show_layout( cr, text->layout );
|
||||
|
||||
cairo_destroy( cr );
|
||||
|
||||
g_mutex_unlock( vips_text_lock );
|
||||
|
||||
vips_image_init_fields( create->out,
|
||||
text->bitmap.width, text->bitmap.rows, 1,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_MULTIBAND,
|
||||
1.0, 1.0 );
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
create->out->Xoffset = extents.left;
|
||||
create->out->Yoffset = extents.top;
|
||||
if( text->rgba ) {
|
||||
int y;
|
||||
|
||||
for( y = 0; y < text->bitmap.rows; y++ )
|
||||
if( vips_image_write_line( create->out, y,
|
||||
(VipsPel *) text->bitmap.buffer +
|
||||
y * text->bitmap.pitch ) )
|
||||
/* Cairo makes pre-multipled BRGA -- we must byteswap and
|
||||
* unpremultiply.
|
||||
*/
|
||||
for( y = 0; y < image->Ysize; y++ )
|
||||
vips__premultiplied_bgra2rgba(
|
||||
(guint32 *)
|
||||
VIPS_IMAGE_ADDR( image, 0, y ),
|
||||
image->Xsize );
|
||||
}
|
||||
else {
|
||||
/* We just want the alpha channel.
|
||||
*/
|
||||
if( vips_extract_band( image, &t[1], 3, NULL ) ||
|
||||
vips_copy( t[1], &t[2],
|
||||
"interpretation", VIPS_INTERPRETATION_MULTIBAND,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
image = t[2];
|
||||
}
|
||||
|
||||
if( vips_image_write( image, create->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -534,6 +576,13 @@ vips_text_class_init( VipsTextClass *class )
|
|||
G_STRUCT_OFFSET( VipsText, fontfile ),
|
||||
NULL );
|
||||
|
||||
VIPS_ARG_BOOL( class, "rgba", 9,
|
||||
_( "RGBA" ),
|
||||
_( "Enable RGBA output" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsText, rgba ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -541,11 +590,10 @@ vips_text_init( VipsText *text )
|
|||
{
|
||||
text->align = VIPS_ALIGN_LOW;
|
||||
text->dpi = 72;
|
||||
text->bitmap.buffer = NULL;
|
||||
VIPS_SETSTR( text->font, "sans 12" );
|
||||
}
|
||||
|
||||
#endif /*HAVE_PANGOFT2*/
|
||||
#endif /*HAVE_PANGOCAIRO*/
|
||||
|
||||
/**
|
||||
* vips_text:
|
||||
|
@ -563,17 +611,22 @@ vips_text_init( VipsText *text )
|
|||
* * @justify: %gboolean, justify lines
|
||||
* * @dpi: %gint, render at this resolution
|
||||
* * @autofit_dpi: %gint, read out auto-fitted DPI
|
||||
* * @rgba: %gboolean, enable RGBA output
|
||||
* * @spacing: %gint, space lines by this in points
|
||||
*
|
||||
* Draw the string @text to an image. @out is a one-band 8-bit
|
||||
* Draw the string @text to an image. @out is normally a one-band 8-bit
|
||||
* unsigned char image, with 0 for no text and 255 for text. Values between
|
||||
* are used for anti-aliasing.
|
||||
*
|
||||
* Set @rgba to enable RGBA output. This is useful for colour emoji rendering,
|
||||
* or support for pango markup features like `<span
|
||||
* foreground="red">Red!</span>`.
|
||||
*
|
||||
* @text is the text to render as a UTF-8 string. It can contain Pango markup,
|
||||
* for example "<i>The</i>Guardian".
|
||||
* for example `<i>The</i>Guardian`.
|
||||
*
|
||||
* @font is the font to render with, as a fontconfig name. Examples might be
|
||||
* "sans 12" or perhaps "bitstream charter bold 10".
|
||||
* `sans 12` or perhaps `bitstream charter bold 10`.
|
||||
*
|
||||
* You can specify a font to load with @fontfile. You'll need to also set the
|
||||
* name of the font with @font.
|
||||
|
|
|
@ -1,72 +1,78 @@
|
|||
if ENABLE_NSGIF
|
||||
SUBDIRS = libnsgif
|
||||
endif
|
||||
|
||||
noinst_LTLIBRARIES = libforeign.la
|
||||
|
||||
libforeign_la_SOURCES = \
|
||||
pforeign.h \
|
||||
heifload.c \
|
||||
heifsave.c \
|
||||
niftiload.c \
|
||||
niftisave.c \
|
||||
quantise.c \
|
||||
exif.c \
|
||||
gifload.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 =
|
||||
EXTRA_DIST = libnsgif
|
||||
|
||||
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
|
||||
|
||||
|
|
|
@ -366,7 +366,8 @@ vips_gsf_path( VipsGsfDirectory *tree, const char *name, ... )
|
|||
* path we are creating.
|
||||
*/
|
||||
tree->file_count += 1;
|
||||
tree->filename_lengths += strlen( tree->out->name ) + strlen( name ) + 1;
|
||||
tree->filename_lengths +=
|
||||
strlen( tree->out->name ) + strlen( name ) + 1;
|
||||
|
||||
dir = tree;
|
||||
va_start( ap, name );
|
||||
|
|
|
@ -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 );
|
||||
|
@ -2187,22 +2194,25 @@ vips_foreign_operation_init( void )
|
|||
extern GType vips_foreign_load_nifti_source_get_type( void );
|
||||
extern GType vips_foreign_save_nifti_get_type( void );
|
||||
|
||||
extern GType vips_foreign_load_gif_file_get_type( void );
|
||||
extern GType vips_foreign_load_gif_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_gif_source_get_type( void );
|
||||
extern GType vips_foreign_load_nsgif_file_get_type( void );
|
||||
extern GType vips_foreign_load_nsgif_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_nsgif_source_get_type( void );
|
||||
|
||||
vips_foreign_load_csv_file_get_type();
|
||||
vips_foreign_load_csv_source_get_type();
|
||||
vips_foreign_save_csv_file_get_type();
|
||||
vips_foreign_save_csv_target_get_type();
|
||||
|
||||
vips_foreign_load_matrix_file_get_type();
|
||||
vips_foreign_load_matrix_source_get_type();
|
||||
vips_foreign_save_matrix_file_get_type();
|
||||
vips_foreign_save_matrix_target_get_type();
|
||||
vips_foreign_print_matrix_get_type();
|
||||
|
||||
vips_foreign_load_raw_get_type();
|
||||
vips_foreign_save_raw_get_type();
|
||||
vips_foreign_save_raw_fd_get_type();
|
||||
|
||||
vips_foreign_load_vips_file_get_type();
|
||||
vips_foreign_load_vips_source_get_type();
|
||||
vips_foreign_save_vips_file_get_type();
|
||||
|
@ -2246,11 +2256,20 @@ vips_foreign_operation_init( void )
|
|||
vips_foreign_load_svg_source_get_type();
|
||||
#endif /*HAVE_RSVG*/
|
||||
|
||||
#ifdef HAVE_GIFLIB
|
||||
vips_foreign_load_gif_file_get_type();
|
||||
vips_foreign_load_gif_buffer_get_type();
|
||||
vips_foreign_load_gif_source_get_type();
|
||||
#endif /*HAVE_GIFLIB*/
|
||||
#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_buffer_get_type();
|
||||
vips_foreign_load_nsgif_source_get_type();
|
||||
#endif /*HAVE_NSGIF*/
|
||||
|
||||
#ifdef HAVE_GSF
|
||||
vips_foreign_save_dz_file_get_type();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
|
@ -321,6 +321,7 @@ vips_foreign_save_heif_build( VipsObject *object )
|
|||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object;
|
||||
|
||||
const char *filename;
|
||||
struct heif_error error;
|
||||
struct heif_writer writer;
|
||||
char *chroma;
|
||||
|
@ -335,6 +336,15 @@ vips_foreign_save_heif_build( VipsObject *object )
|
|||
if( vips_copy( save->ready, &heif->image, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Compression defaults to VIPS_FOREIGN_HEIF_COMPRESSION_AV1 for .avif
|
||||
* suffix.
|
||||
*/
|
||||
filename = vips_connection_filename( VIPS_CONNECTION( heif->target ) );
|
||||
if( !vips_object_argument_isset( object, "compression" ) &&
|
||||
filename &&
|
||||
vips_iscasepostfix( filename, ".avif" ) )
|
||||
heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1;
|
||||
|
||||
error = heif_context_get_encoder_for_format( heif->ctx,
|
||||
(enum heif_compression_format) heif->compression,
|
||||
&heif->encoder );
|
||||
|
@ -370,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 &&
|
||||
|
@ -566,7 +576,7 @@ vips_foreign_save_heif_file_class_init( VipsForeignSaveHeifFileClass *class )
|
|||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
_( "Filename to load from" ),
|
||||
_( "Filename to save to" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveHeifFile, filename ),
|
||||
NULL );
|
||||
|
@ -722,12 +732,13 @@ vips_foreign_save_heif_target_init( VipsForeignSaveHeifTarget *target )
|
|||
*
|
||||
* Set @lossless %TRUE to switch to lossless compression.
|
||||
*
|
||||
* Use @compression to set the encoder e.g. HEVC, AVC, AV1
|
||||
* Use @compression to set the encoder e.g. HEVC, AVC, AV1. It defaults to AV1
|
||||
* if the target filename ends with ".avif", otherwise HEVC.
|
||||
*
|
||||
* 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().
|
||||
|
|
File diff suppressed because it is too large
Load Diff
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
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
EXTRA_DIST = \
|
||||
README-ns \
|
||||
README.md \
|
||||
patches \
|
||||
update.sh \
|
||||
utils
|
||||
|
||||
noinst_LTLIBRARIES = libnsgif.la
|
||||
|
||||
libnsgif_la_SOURCES = \
|
||||
libnsgif.h \
|
||||
libnsgif.c \
|
||||
lzw.c \
|
||||
lzw.h
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
libnsgif - Decoding GIF files
|
||||
=============================
|
||||
|
||||
The functions provided by this library allow for efficient progressive
|
||||
GIF decoding. Whilst the initialisation does not ensure that there is
|
||||
sufficient image data to complete the entire frame, it does ensure
|
||||
that the information provided is valid. Any subsequent attempts to
|
||||
decode an initialised GIF are guaranteed to succeed, and any bytes of
|
||||
the image not present are assumed to be totally transparent.
|
||||
|
||||
To begin decoding a GIF, the 'gif' structure must be initialised with
|
||||
the 'gif_data' and 'buffer_size' set to their initial values. The
|
||||
'buffer_position' should initially be 0, and will be internally
|
||||
updated as the decoding commences. The caller should then repeatedly
|
||||
call gif_initialise() with the structure until the function returns 1,
|
||||
or no more data is avaliable.
|
||||
|
||||
Once the initialisation has begun, the decoder completes the variables
|
||||
'frame_count' and 'frame_count_partial'. The former being the total
|
||||
number of frames that have been successfully initialised, and the
|
||||
latter being the number of frames that a partial amount of data is
|
||||
available for. This assists the caller in managing the animation
|
||||
whilst decoding is continuing.
|
||||
|
||||
To decode a frame, the caller must use gif_decode_frame() which
|
||||
updates the current 'frame_image' to reflect the desired frame. The
|
||||
required 'disposal_method' is also updated to reflect how the frame
|
||||
should be plotted. The caller must not assume that the current
|
||||
'frame_image' will be valid between calls if initialisation is still
|
||||
occuring, and should either always request that the frame is decoded
|
||||
(no processing will occur if the 'decoded_frame' has not been
|
||||
invalidated by initialisation) or perform the check itself.
|
||||
|
||||
It should be noted that gif_finalise() should always be called, even
|
||||
if no frames were initialised. Additionally, it is the responsibility
|
||||
of the caller to free 'gif_data'.
|
|
@ -0,0 +1,16 @@
|
|||
# libnsgif
|
||||
|
||||
This is [libnsgif](https://www.netsurf-browser.org/projects/libnsgif/),
|
||||
but within the libvips build system.
|
||||
|
||||
# To update
|
||||
|
||||
Run `./update.sh` to update this copy of libnsgif from the upstream repo. It
|
||||
will also patch libnsgif.c to prevent it modifying the input.
|
||||
|
||||
Last updated 28 Feb 2021.
|
||||
|
||||
# To do
|
||||
|
||||
No attempt made to run tests or build docs. Though the gif loader is tested as
|
||||
part of the libvips test suite.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright 2004 Richard Wilson <richard.wilson@netsurf-browser.org>
|
||||
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
|
||||
*
|
||||
* This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
|
||||
* Licenced under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Interface to progressive animated GIF file decoding.
|
||||
*/
|
||||
|
||||
#ifndef _LIBNSGIF_H_
|
||||
#define _LIBNSGIF_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Error return values */
|
||||
typedef enum {
|
||||
GIF_WORKING = 1,
|
||||
GIF_OK = 0,
|
||||
GIF_INSUFFICIENT_FRAME_DATA = -1,
|
||||
GIF_FRAME_DATA_ERROR = -2,
|
||||
GIF_INSUFFICIENT_DATA = -3,
|
||||
GIF_DATA_ERROR = -4,
|
||||
GIF_INSUFFICIENT_MEMORY = -5,
|
||||
GIF_FRAME_NO_DISPLAY = -6,
|
||||
GIF_END_OF_FRAME = -7
|
||||
} gif_result;
|
||||
|
||||
/** GIF frame data */
|
||||
typedef struct gif_frame {
|
||||
/** whether the frame should be displayed/animated */
|
||||
bool display;
|
||||
/** delay (in cs) before animating the frame */
|
||||
unsigned int frame_delay;
|
||||
|
||||
/* Internal members are listed below */
|
||||
|
||||
/** offset (in bytes) to the GIF frame data */
|
||||
unsigned int frame_pointer;
|
||||
/** whether the frame has previously been used */
|
||||
bool virgin;
|
||||
/** whether the frame is totally opaque */
|
||||
bool opaque;
|
||||
/** whether a forcable screen redraw is required */
|
||||
bool redraw_required;
|
||||
/** how the previous frame should be disposed; affects plotting */
|
||||
unsigned char disposal_method;
|
||||
/** whether we acknoledge transparency */
|
||||
bool transparency;
|
||||
/** the index designating a transparent pixel */
|
||||
unsigned char transparency_index;
|
||||
/** x co-ordinate of redraw rectangle */
|
||||
unsigned int redraw_x;
|
||||
/** y co-ordinate of redraw rectangle */
|
||||
unsigned int redraw_y;
|
||||
/** width of redraw rectangle */
|
||||
unsigned int redraw_width;
|
||||
/** height of redraw rectangle */
|
||||
unsigned int redraw_height;
|
||||
} gif_frame;
|
||||
|
||||
/* API for Bitmap callbacks */
|
||||
typedef void* (*gif_bitmap_cb_create)(int width, int height);
|
||||
typedef void (*gif_bitmap_cb_destroy)(void *bitmap);
|
||||
typedef unsigned char* (*gif_bitmap_cb_get_buffer)(void *bitmap);
|
||||
typedef void (*gif_bitmap_cb_set_opaque)(void *bitmap, bool opaque);
|
||||
typedef bool (*gif_bitmap_cb_test_opaque)(void *bitmap);
|
||||
typedef void (*gif_bitmap_cb_modified)(void *bitmap);
|
||||
|
||||
/** Bitmap callbacks function table */
|
||||
typedef struct gif_bitmap_callback_vt {
|
||||
/** Create a bitmap. */
|
||||
gif_bitmap_cb_create bitmap_create;
|
||||
/** Free a bitmap. */
|
||||
gif_bitmap_cb_destroy bitmap_destroy;
|
||||
/** Return a pointer to the pixel data in a bitmap. */
|
||||
gif_bitmap_cb_get_buffer bitmap_get_buffer;
|
||||
|
||||
/* Members below are optional */
|
||||
|
||||
/** Sets whether a bitmap should be plotted opaque. */
|
||||
gif_bitmap_cb_set_opaque bitmap_set_opaque;
|
||||
/** Tests whether a bitmap has an opaque alpha channel. */
|
||||
gif_bitmap_cb_test_opaque bitmap_test_opaque;
|
||||
/** The bitmap image has changed, so flush any persistant cache. */
|
||||
gif_bitmap_cb_modified bitmap_modified;
|
||||
} gif_bitmap_callback_vt;
|
||||
|
||||
/** GIF animation data */
|
||||
typedef struct gif_animation {
|
||||
/** LZW decode context */
|
||||
void *lzw_ctx;
|
||||
/** callbacks for bitmap functions */
|
||||
gif_bitmap_callback_vt bitmap_callbacks;
|
||||
/** pointer to GIF data */
|
||||
unsigned char *gif_data;
|
||||
/** width of GIF (may increase during decoding) */
|
||||
unsigned int width;
|
||||
/** heigth of GIF (may increase during decoding) */
|
||||
unsigned int height;
|
||||
/** number of frames decoded */
|
||||
unsigned int frame_count;
|
||||
/** number of frames partially decoded */
|
||||
unsigned int frame_count_partial;
|
||||
/** decoded frames */
|
||||
gif_frame *frames;
|
||||
/** current frame decoded to bitmap */
|
||||
int decoded_frame;
|
||||
/** currently decoded image; stored as bitmap from bitmap_create callback */
|
||||
void *frame_image;
|
||||
/** number of times to loop animation */
|
||||
int loop_count;
|
||||
|
||||
/* Internal members are listed below */
|
||||
|
||||
/** current index into GIF data */
|
||||
unsigned int buffer_position;
|
||||
/** total number of bytes of GIF data available */
|
||||
unsigned int buffer_size;
|
||||
/** current number of frame holders */
|
||||
unsigned int frame_holders;
|
||||
/** index in the colour table for the background colour */
|
||||
unsigned int background_index;
|
||||
/** image aspect ratio (ignored) */
|
||||
unsigned int aspect_ratio;
|
||||
/** size of colour table (in entries) */
|
||||
unsigned int colour_table_size;
|
||||
/** whether the GIF has a global colour table */
|
||||
bool global_colours;
|
||||
/** global colour table */
|
||||
unsigned int *global_colour_table;
|
||||
/** local colour table */
|
||||
unsigned int *local_colour_table;
|
||||
|
||||
/** previous frame for GIF_FRAME_RESTORE */
|
||||
void *prev_frame;
|
||||
/** previous frame index */
|
||||
int prev_index;
|
||||
/** previous frame width */
|
||||
unsigned prev_width;
|
||||
/** previous frame height */
|
||||
unsigned prev_height;
|
||||
} gif_animation;
|
||||
|
||||
/**
|
||||
* Initialises necessary gif_animation members.
|
||||
*/
|
||||
void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
|
||||
|
||||
/**
|
||||
* Initialises any workspace held by the animation and attempts to decode
|
||||
* any information that hasn't already been decoded.
|
||||
* If an error occurs, all previously decoded frames are retained.
|
||||
*
|
||||
* @return Error return value.
|
||||
* - GIF_FRAME_DATA_ERROR for GIF frame data error
|
||||
* - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to process
|
||||
* any more frames
|
||||
* - GIF_INSUFFICIENT_MEMORY for memory error
|
||||
* - GIF_DATA_ERROR for GIF error
|
||||
* - GIF_INSUFFICIENT_DATA for insufficient data to do anything
|
||||
* - GIF_OK for successful decoding
|
||||
* - GIF_WORKING for successful decoding if more frames are expected
|
||||
*/
|
||||
gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data);
|
||||
|
||||
/**
|
||||
* Decodes a GIF frame.
|
||||
*
|
||||
* @return Error return value. If a frame does not contain any image data,
|
||||
* GIF_OK is returned and gif->current_error is set to
|
||||
* GIF_FRAME_NO_DISPLAY
|
||||
* - GIF_FRAME_DATA_ERROR for GIF frame data error
|
||||
* - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
|
||||
* - GIF_DATA_ERROR for GIF error (invalid frame header)
|
||||
* - GIF_INSUFFICIENT_DATA for insufficient data to do anything
|
||||
* - GIF_INSUFFICIENT_MEMORY for insufficient memory to process
|
||||
* - GIF_OK for successful decoding
|
||||
*/
|
||||
gif_result gif_decode_frame(gif_animation *gif, unsigned int frame);
|
||||
|
||||
/**
|
||||
* Releases any workspace held by a gif
|
||||
*/
|
||||
void gif_finalise(gif_animation *gif);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,555 @@
|
|||
/*
|
||||
* This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
|
||||
* Licensed under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
|
||||
* Copyright 2021 Michael Drake <tlsa@netsurf-browser.org>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lzw.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief LZW decompression (implementation)
|
||||
*
|
||||
* Decoder for GIF LZW data.
|
||||
*/
|
||||
|
||||
/** Maximum number of lzw table entries. */
|
||||
#define LZW_TABLE_ENTRY_MAX (1u << LZW_CODE_MAX)
|
||||
|
||||
/**
|
||||
* Context for reading LZW data.
|
||||
*
|
||||
* LZW data is split over multiple sub-blocks. Each sub-block has a
|
||||
* byte at the start, which says the sub-block size, and then the data.
|
||||
* Zero-size sub-blocks have no data, and the biggest sub-block size is
|
||||
* 255, which means there are 255 bytes of data following the sub-block
|
||||
* size entry.
|
||||
*
|
||||
* Note that an individual LZW code can be split over up to three sub-blocks.
|
||||
*/
|
||||
struct lzw_read_ctx {
|
||||
const uint8_t *restrict data; /**< Pointer to start of input data */
|
||||
uint32_t data_len; /**< Input data length */
|
||||
uint32_t data_sb_next; /**< Offset to sub-block size */
|
||||
|
||||
const uint8_t *sb_data; /**< Pointer to current sub-block in data */
|
||||
size_t sb_bit; /**< Current bit offset in sub-block */
|
||||
uint32_t sb_bit_count; /**< Bit count in sub-block */
|
||||
};
|
||||
|
||||
/**
|
||||
* LZW table entry.
|
||||
*
|
||||
* Records in the table are composed of 1 or more entries.
|
||||
* Entries refer to the entry they extend which can be followed to compose
|
||||
* the complete record. To compose the record in reverse order, take
|
||||
* the `value` from each entry, and move to the entry it extends.
|
||||
* If the extended entries index is < the current clear_code, then it
|
||||
* is the last entry in the record.
|
||||
*/
|
||||
struct lzw_table_entry {
|
||||
uint8_t value; /**< Last value for record ending at entry. */
|
||||
uint8_t first; /**< First value in entry's entire record. */
|
||||
uint16_t count; /**< Count of values in this entry's record. */
|
||||
uint16_t extends; /**< Offset in table to previous entry. */
|
||||
};
|
||||
|
||||
/**
|
||||
* LZW decompression context.
|
||||
*/
|
||||
struct lzw_ctx {
|
||||
struct lzw_read_ctx input; /**< Input reading context */
|
||||
|
||||
uint32_t prev_code; /**< Code read from input previously. */
|
||||
uint32_t prev_code_first; /**< First value of previous code. */
|
||||
uint32_t prev_code_count; /**< Total values for previous code. */
|
||||
|
||||
uint32_t initial_code_size; /**< Starting LZW code size. */
|
||||
|
||||
uint32_t code_size; /**< Current LZW code size. */
|
||||
uint32_t code_max; /**< Max code value for current code size. */
|
||||
|
||||
uint32_t clear_code; /**< Special Clear code value */
|
||||
uint32_t eoi_code; /**< Special End of Information code value */
|
||||
|
||||
uint32_t table_size; /**< Next position in table to fill. */
|
||||
|
||||
uint32_t output_code; /**< Code that has been partially output. */
|
||||
uint32_t output_left; /**< Number of values left for output_code. */
|
||||
|
||||
uint32_t transparency_idx; /**< Index representing transparency. */
|
||||
uint32_t *restrict colour_map; /**< Index to pixel colour mapping */
|
||||
|
||||
/** Output value stack. */
|
||||
uint8_t stack_base[LZW_TABLE_ENTRY_MAX];
|
||||
|
||||
/** LZW code table. Generated during decode. */
|
||||
struct lzw_table_entry table[LZW_TABLE_ENTRY_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
lzw_result lzw_context_create(struct lzw_ctx **ctx)
|
||||
{
|
||||
struct lzw_ctx *c = malloc(sizeof(*c));
|
||||
if (c == NULL) {
|
||||
return LZW_NO_MEM;
|
||||
}
|
||||
|
||||
*ctx = c;
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
void lzw_context_destroy(struct lzw_ctx *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Advance the context to the next sub-block in the input data.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated on success.
|
||||
* \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
|
||||
*/
|
||||
static lzw_result lzw__block_advance(struct lzw_read_ctx *restrict ctx)
|
||||
{
|
||||
uint32_t block_size;
|
||||
uint32_t next_block_pos = ctx->data_sb_next;
|
||||
const uint8_t *data_next = ctx->data + next_block_pos;
|
||||
|
||||
if (next_block_pos >= ctx->data_len) {
|
||||
return LZW_NO_DATA;
|
||||
}
|
||||
|
||||
block_size = *data_next;
|
||||
|
||||
if ((next_block_pos + block_size) >= ctx->data_len) {
|
||||
return LZW_NO_DATA;
|
||||
}
|
||||
|
||||
ctx->sb_bit = 0;
|
||||
ctx->sb_bit_count = block_size * 8;
|
||||
|
||||
if (block_size == 0) {
|
||||
ctx->data_sb_next += 1;
|
||||
return LZW_OK_EOD;
|
||||
}
|
||||
|
||||
ctx->sb_data = data_next + 1;
|
||||
ctx->data_sb_next += block_size + 1;
|
||||
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next LZW code of given size from the raw input data.
|
||||
*
|
||||
* Reads codes from the input data stream coping with GIF data sub-blocks.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] code_size Size of LZW code to get from data.
|
||||
* \param[out] code_out Returns an LZW code on success.
|
||||
* \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
|
||||
*/
|
||||
static inline lzw_result lzw__read_code(
|
||||
struct lzw_read_ctx *restrict ctx,
|
||||
uint32_t code_size,
|
||||
uint32_t *restrict code_out)
|
||||
{
|
||||
uint32_t code = 0;
|
||||
uint32_t current_bit = ctx->sb_bit & 0x7;
|
||||
|
||||
if (ctx->sb_bit + 24 <= ctx->sb_bit_count) {
|
||||
/* Fast path: read three bytes from this sub-block */
|
||||
const uint8_t *data = ctx->sb_data + (ctx->sb_bit >> 3);
|
||||
code |= *data++ << 0;
|
||||
code |= *data++ << 8;
|
||||
code |= *data << 16;
|
||||
ctx->sb_bit += code_size;
|
||||
} else {
|
||||
/* Slow path: code spans sub-blocks */
|
||||
uint8_t byte_advance = (current_bit + code_size) >> 3;
|
||||
uint8_t byte = 0;
|
||||
uint8_t bits_remaining_0 = (code_size < (8u - current_bit)) ?
|
||||
code_size : (8u - current_bit);
|
||||
uint8_t bits_remaining_1 = code_size - bits_remaining_0;
|
||||
uint8_t bits_used[3] = {
|
||||
[0] = bits_remaining_0,
|
||||
[1] = bits_remaining_1 < 8 ? bits_remaining_1 : 8,
|
||||
[2] = bits_remaining_1 - 8,
|
||||
};
|
||||
|
||||
assert(byte_advance <= 2);
|
||||
|
||||
while (true) {
|
||||
const uint8_t *data = ctx->sb_data;
|
||||
lzw_result res;
|
||||
|
||||
/* Get any data from end of this sub-block */
|
||||
while (byte <= byte_advance &&
|
||||
ctx->sb_bit < ctx->sb_bit_count) {
|
||||
code |= data[ctx->sb_bit >> 3] << (byte << 3);
|
||||
ctx->sb_bit += bits_used[byte];
|
||||
byte++;
|
||||
}
|
||||
|
||||
/* Check if we have all we need */
|
||||
if (byte > byte_advance) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next sub-block */
|
||||
res = lzw__block_advance(ctx);
|
||||
if (res != LZW_OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*code_out = (code >> current_bit) & ((1 << code_size) - 1);
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear LZW code table.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \return LZW_OK or error code.
|
||||
*/
|
||||
static inline void lzw__clear_table(
|
||||
struct lzw_ctx *ctx)
|
||||
{
|
||||
/* Reset table building context */
|
||||
ctx->code_size = ctx->initial_code_size;
|
||||
ctx->code_max = (1 << ctx->initial_code_size) - 1;
|
||||
ctx->table_size = ctx->eoi_code + 1;
|
||||
}
|
||||
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
lzw_result lzw_decode_init(
|
||||
struct lzw_ctx *ctx,
|
||||
const uint8_t *compressed_data,
|
||||
uint32_t compressed_data_len,
|
||||
uint32_t compressed_data_pos,
|
||||
uint8_t minimum_code_size)
|
||||
{
|
||||
struct lzw_table_entry *table = ctx->table;
|
||||
|
||||
if (minimum_code_size >= LZW_CODE_MAX) {
|
||||
return LZW_BAD_ICODE;
|
||||
}
|
||||
|
||||
/* Initialise the input reading context */
|
||||
ctx->input.data = compressed_data;
|
||||
ctx->input.data_len = compressed_data_len;
|
||||
ctx->input.data_sb_next = compressed_data_pos;
|
||||
|
||||
ctx->input.sb_bit = 0;
|
||||
ctx->input.sb_bit_count = 0;
|
||||
|
||||
/* Initialise the table building context */
|
||||
ctx->initial_code_size = minimum_code_size + 1;
|
||||
|
||||
ctx->clear_code = (1 << minimum_code_size) + 0;
|
||||
ctx->eoi_code = (1 << minimum_code_size) + 1;
|
||||
|
||||
ctx->output_left = 0;
|
||||
|
||||
/* Initialise the standard table entries */
|
||||
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
|
||||
table[i].first = i;
|
||||
table[i].value = i;
|
||||
table[i].count = 1;
|
||||
}
|
||||
|
||||
lzw__clear_table(ctx);
|
||||
ctx->prev_code = ctx->clear_code;
|
||||
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new table entry.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] code Last value code for new table entry.
|
||||
*/
|
||||
static inline void lzw__table_add_entry(
|
||||
struct lzw_ctx *ctx,
|
||||
uint32_t code)
|
||||
{
|
||||
struct lzw_table_entry *entry = &ctx->table[ctx->table_size];
|
||||
|
||||
entry->value = code;
|
||||
entry->first = ctx->prev_code_first;
|
||||
entry->count = ctx->prev_code_count + 1;
|
||||
entry->extends = ctx->prev_code;
|
||||
|
||||
ctx->table_size++;
|
||||
}
|
||||
|
||||
typedef uint32_t (*lzw_writer_fn)(
|
||||
struct lzw_ctx *ctx,
|
||||
void *restrict output,
|
||||
uint32_t length,
|
||||
uint32_t used,
|
||||
uint32_t code,
|
||||
uint32_t left);
|
||||
|
||||
/**
|
||||
* Get the next LZW code and write its value(s) to output buffer.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] output Array to write output values into.
|
||||
* \param[in] length Size of output array.
|
||||
* \param[in] write_pixels Function for writing pixels to output.
|
||||
* \param[in,out] used Number of values written. Updated on exit.
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
static inline lzw_result lzw__decode(struct lzw_ctx *ctx,
|
||||
void *restrict output,
|
||||
uint32_t length,
|
||||
lzw_writer_fn write_pixels,
|
||||
uint32_t *restrict used)
|
||||
{
|
||||
lzw_result res;
|
||||
uint32_t code;
|
||||
|
||||
/* Get a new code from the input */
|
||||
res = lzw__read_code(&ctx->input, ctx->code_size, &code);
|
||||
if (res != LZW_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Handle the new code */
|
||||
if (code == ctx->eoi_code) {
|
||||
/* Got End of Information code */
|
||||
return LZW_EOI_CODE;
|
||||
|
||||
} else if (code > ctx->table_size) {
|
||||
/* Code is invalid */
|
||||
return LZW_BAD_CODE;
|
||||
|
||||
} else if (code == ctx->clear_code) {
|
||||
lzw__clear_table(ctx);
|
||||
} else {
|
||||
if (ctx->prev_code == ctx->clear_code) {
|
||||
if (code > ctx->clear_code) {
|
||||
return LZW_BAD_ICODE;
|
||||
}
|
||||
|
||||
} else if (ctx->table_size < LZW_TABLE_ENTRY_MAX) {
|
||||
uint32_t size = ctx->table_size;
|
||||
lzw__table_add_entry(ctx, (code < size) ?
|
||||
ctx->table[code].first :
|
||||
ctx->prev_code_first);
|
||||
|
||||
/* Ensure code size is increased, if needed. */
|
||||
if (size == ctx->code_max &&
|
||||
ctx->code_size < LZW_CODE_MAX) {
|
||||
ctx->code_size++;
|
||||
ctx->code_max = (1 << ctx->code_size) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
*used += write_pixels(ctx, output, length, *used, code,
|
||||
ctx->table[code].count);
|
||||
}
|
||||
|
||||
/* Store details of this code as "previous code" to the context. */
|
||||
ctx->prev_code_first = ctx->table[code].first;
|
||||
ctx->prev_code_count = ctx->table[code].count;
|
||||
ctx->prev_code = code;
|
||||
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write values for this code to the output stack.
|
||||
*
|
||||
* If there isn't enough space in the output stack, this function will write
|
||||
* the as many as it can into the output. If `ctx->output_left > 0` after
|
||||
* this call, then there is more data for this code left to output. The code
|
||||
* is stored to the context as `ctx->output_code`.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] output Array to write output values into.
|
||||
* \param[in] length Size of output array.
|
||||
* \param[in] used Current position in output array.
|
||||
* \param[in] code LZW code to output values for.
|
||||
* \param[in] left Number of values remaining to output for this value.
|
||||
* \return Number of pixel values written.
|
||||
*/
|
||||
static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx,
|
||||
void *restrict output,
|
||||
uint32_t length,
|
||||
uint32_t used,
|
||||
uint32_t code,
|
||||
uint32_t left)
|
||||
{
|
||||
uint8_t *restrict output_pos = (uint8_t *)output + used;
|
||||
const struct lzw_table_entry * const table = ctx->table;
|
||||
uint32_t space = length - used;
|
||||
uint32_t count = left;
|
||||
|
||||
if (count > space) {
|
||||
left = count - space;
|
||||
count = space;
|
||||
} else {
|
||||
left = 0;
|
||||
}
|
||||
|
||||
ctx->output_code = code;
|
||||
ctx->output_left = left;
|
||||
|
||||
/* Skip over any values we don't have space for. */
|
||||
for (unsigned i = left; i != 0; i--) {
|
||||
const struct lzw_table_entry *entry = table + code;
|
||||
code = entry->extends;
|
||||
}
|
||||
|
||||
output_pos += count;
|
||||
for (unsigned i = count; i != 0; i--) {
|
||||
const struct lzw_table_entry *entry = table + code;
|
||||
*--output_pos = entry->value;
|
||||
code = entry->extends;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
lzw_result lzw_decode(struct lzw_ctx *ctx,
|
||||
const uint8_t *restrict* const restrict data,
|
||||
uint32_t *restrict used)
|
||||
{
|
||||
*used = 0;
|
||||
*data = ctx->stack_base;
|
||||
return lzw__decode(ctx, ctx->stack_base, sizeof(ctx->stack_base),
|
||||
lzw__write_pixels, used);
|
||||
}
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
lzw_result lzw_decode_continuous(struct lzw_ctx *ctx,
|
||||
const uint8_t ** const data,
|
||||
uint32_t *restrict used)
|
||||
{
|
||||
*used = 0;
|
||||
*data = ctx->stack_base;
|
||||
|
||||
if (ctx->output_left != 0) {
|
||||
*used += lzw__write_pixels(ctx,
|
||||
ctx->stack_base, sizeof(ctx->stack_base), *used,
|
||||
ctx->output_code, ctx->output_left);
|
||||
}
|
||||
|
||||
while (*used != sizeof(ctx->stack_base)) {
|
||||
lzw_result res = lzw__decode(ctx,
|
||||
ctx->stack_base, sizeof(ctx->stack_base),
|
||||
lzw__write_pixels, used);
|
||||
if (res != LZW_OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write colour mapped values for this code to the output stack.
|
||||
*
|
||||
* If there isn't enough space in the output stack, this function will write
|
||||
* the as many as it can into the output. If `ctx->output_left > 0` after
|
||||
* this call, then there is more data for this code left to output. The code
|
||||
* is stored to the context as `ctx->output_code`.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] output Array to write output values into.
|
||||
* \param[in] length Size of output array.
|
||||
* \param[in] used Current position in output array.
|
||||
* \param[in] code LZW code to output values for.
|
||||
* \param[in] left Number of values remaining to output for this value.
|
||||
* \return Number of pixel values written.
|
||||
*/
|
||||
static inline uint32_t lzw__write_pixels_map(struct lzw_ctx *ctx,
|
||||
void *restrict buffer,
|
||||
uint32_t length,
|
||||
uint32_t used,
|
||||
uint32_t code,
|
||||
uint32_t left)
|
||||
{
|
||||
uint32_t *restrict stack_pos = (uint32_t *)buffer + used;
|
||||
const struct lzw_table_entry * const table = ctx->table;
|
||||
uint32_t space = length - used;
|
||||
uint32_t count = left;
|
||||
|
||||
if (count > space) {
|
||||
left = count - space;
|
||||
count = space;
|
||||
} else {
|
||||
left = 0;
|
||||
}
|
||||
|
||||
ctx->output_code = code;
|
||||
ctx->output_left = left;
|
||||
|
||||
for (unsigned i = left; i != 0; i--) {
|
||||
const struct lzw_table_entry *entry = table + code;
|
||||
code = entry->extends;
|
||||
}
|
||||
|
||||
stack_pos += count;
|
||||
for (unsigned i = count; i != 0; i--) {
|
||||
const struct lzw_table_entry *entry = table + code;
|
||||
--stack_pos;
|
||||
if (entry->value != ctx->transparency_idx) {
|
||||
*stack_pos = ctx->colour_map[entry->value];
|
||||
}
|
||||
code = entry->extends;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Exported function, documented in lzw.h */
|
||||
lzw_result lzw_decode_map_continuous(struct lzw_ctx *ctx,
|
||||
uint32_t transparency_idx,
|
||||
uint32_t *restrict colour_map,
|
||||
uint32_t *restrict data,
|
||||
uint32_t length,
|
||||
uint32_t *restrict used)
|
||||
{
|
||||
*used = 0;
|
||||
|
||||
ctx->transparency_idx = transparency_idx;
|
||||
ctx->colour_map = colour_map;
|
||||
|
||||
if (ctx->output_left != 0) {
|
||||
*used += lzw__write_pixels_map(ctx, data, length, *used,
|
||||
ctx->output_code, ctx->output_left);
|
||||
}
|
||||
|
||||
while (*used != sizeof(ctx->stack_base)) {
|
||||
lzw_result res = lzw__decode(ctx, data, length,
|
||||
lzw__write_pixels_map, used);
|
||||
if (res != LZW_OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return LZW_OK;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
|
||||
* Licensed under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef LZW_H_
|
||||
#define LZW_H_
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief LZW decompression (interface)
|
||||
*
|
||||
* Decoder for GIF LZW data.
|
||||
*/
|
||||
|
||||
|
||||
/** Maximum LZW code size in bits */
|
||||
#define LZW_CODE_MAX 12
|
||||
|
||||
|
||||
/* Declare lzw internal context structure */
|
||||
struct lzw_ctx;
|
||||
|
||||
|
||||
/** LZW decoding response codes */
|
||||
typedef enum lzw_result {
|
||||
LZW_OK, /**< Success */
|
||||
LZW_OK_EOD, /**< Success; reached zero-length sub-block */
|
||||
LZW_NO_MEM, /**< Error: Out of memory */
|
||||
LZW_NO_DATA, /**< Error: Out of data */
|
||||
LZW_EOI_CODE, /**< Error: End of Information code */
|
||||
LZW_BAD_ICODE, /**< Error: Bad initial LZW code */
|
||||
LZW_BAD_CODE, /**< Error: Bad LZW code */
|
||||
} lzw_result;
|
||||
|
||||
|
||||
/**
|
||||
* Create an LZW decompression context.
|
||||
*
|
||||
* \param[out] ctx Returns an LZW decompression context. Caller owned,
|
||||
* free with lzw_context_destroy().
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
lzw_result lzw_context_create(
|
||||
struct lzw_ctx **ctx);
|
||||
|
||||
/**
|
||||
* Destroy an LZW decompression context.
|
||||
*
|
||||
* \param[in] ctx The LZW decompression context to destroy.
|
||||
*/
|
||||
void lzw_context_destroy(
|
||||
struct lzw_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Initialise an LZW decompression context for decoding.
|
||||
*
|
||||
* Caller owns neither `stack_base_out` or `stack_pos_out`.
|
||||
*
|
||||
* \param[in] ctx The LZW decompression context to initialise.
|
||||
* \param[in] compressed_data The compressed data.
|
||||
* \param[in] compressed_data_len Byte length of compressed data.
|
||||
* \param[in] compressed_data_pos Start position in data. Must be position
|
||||
* of a size byte at sub-block start.
|
||||
* \param[in] minimum_code_size The LZW Minimum Code Size.
|
||||
* \param[out] stack_base_out Returns base of decompressed data stack.
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
lzw_result lzw_decode_init(
|
||||
struct lzw_ctx *ctx,
|
||||
const uint8_t *compressed_data,
|
||||
uint32_t compressed_data_len,
|
||||
uint32_t compressed_data_pos,
|
||||
uint8_t minimum_code_size);
|
||||
|
||||
/**
|
||||
* Read a single LZW code and write into lzw context owned output buffer.
|
||||
*
|
||||
* Ensure anything in output is used before calling this, as anything
|
||||
* on the there before this call will be trampled.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[out] data Returns pointer to array of output values.
|
||||
* \param[out] used Returns the number of values written to data.
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
lzw_result lzw_decode(struct lzw_ctx *ctx,
|
||||
const uint8_t *restrict *const restrict data,
|
||||
uint32_t *restrict used);
|
||||
|
||||
/**
|
||||
* Read input codes until end of lzw context owned output buffer.
|
||||
*
|
||||
* Ensure anything in output is used before calling this, as anything
|
||||
* on the there before this call will be trampled.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[out] data Returns pointer to array of output values.
|
||||
* \param[out] used Returns the number of values written to data.
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
lzw_result lzw_decode_continuous(struct lzw_ctx *ctx,
|
||||
const uint8_t ** const data,
|
||||
uint32_t *restrict used);
|
||||
|
||||
/**
|
||||
* Read LZW codes into client buffer, mapping output to colours.
|
||||
*
|
||||
* Ensure anything in output is used before calling this, as anything
|
||||
* on the there before this call will be trampled.
|
||||
*
|
||||
* For transparency to work correctly, the given client buffer must have
|
||||
* the values from the previous frame. The transparency_idx should be a value
|
||||
* of 256 or above, if the frame does not have transparency.
|
||||
*
|
||||
* \param[in] ctx LZW reading context, updated.
|
||||
* \param[in] transparency_idx Index representing transparency.
|
||||
* \param[in] colour_map Index to pixel colour mapping
|
||||
* \param[in] data Client buffer to fill with colour mapped values.
|
||||
* \param[in] length Size of output array.
|
||||
* \param[out] used Returns the number of values written to data.
|
||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||
*/
|
||||
lzw_result lzw_decode_map_continuous(struct lzw_ctx *ctx,
|
||||
uint32_t transparency_idx,
|
||||
uint32_t *restrict colour_table,
|
||||
uint32_t *restrict data,
|
||||
uint32_t length,
|
||||
uint32_t *restrict used);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
--- libnsgif-orig.c 2021-02-28 14:10:41.818557190 +0000
|
||||
+++ libnsgif.c 2021-02-28 14:11:55.942285930 +0000
|
||||
@@ -435,20 +435,15 @@
|
||||
block_size = gif_data[0] + 1;
|
||||
/* Check if the frame data runs off the end of the file */
|
||||
if ((int)(gif_bytes - block_size) < 0) {
|
||||
- /* Try to recover by signaling the end of the gif.
|
||||
- * Once we get garbage data, there is no logical way to
|
||||
- * determine where the next frame is. It's probably
|
||||
- * better to partially load the gif than not at all.
|
||||
- */
|
||||
- if (gif_bytes >= 2) {
|
||||
- gif_data[0] = 0;
|
||||
- gif_data[1] = GIF_TRAILER;
|
||||
- gif_bytes = 1;
|
||||
- ++gif_data;
|
||||
- break;
|
||||
- } else {
|
||||
- return GIF_INSUFFICIENT_FRAME_DATA;
|
||||
- }
|
||||
+ /* jcupitt 15/9/19
|
||||
+ *
|
||||
+ * There was code here to set a TRAILER tag. But this
|
||||
+ * wrote to the input buffer, which will not work for
|
||||
+ * libvips, where buffers can be mmaped read only files.
|
||||
+ *
|
||||
+ * Instead, just signal insufficient frame data.
|
||||
+ */
|
||||
+ return GIF_INSUFFICIENT_FRAME_DATA;
|
||||
} else {
|
||||
gif_bytes -= block_size;
|
||||
gif_data += block_size;
|
|
@ -0,0 +1,258 @@
|
|||
/* under libvips, compile with:
|
||||
*
|
||||
* gcc -g -Wall decode_gif.c `pkg-config vips --cflags --libs`
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
|
||||
* Copyright 2008 James Bursa <james@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
|
||||
* Licenced under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include "../libnsgif.h"
|
||||
|
||||
#define BYTES_PER_PIXEL 4
|
||||
#define MAX_IMAGE_BYTES (48 * 1024 * 1024)
|
||||
|
||||
|
||||
static void *bitmap_create(int width, int height)
|
||||
{
|
||||
/* ensure a stupidly large bitmap is not created */
|
||||
if (((long long)width * (long long)height) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL)) {
|
||||
return NULL;
|
||||
}
|
||||
return calloc(width * height, BYTES_PER_PIXEL);
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_set_opaque(void *bitmap, bool opaque)
|
||||
{
|
||||
(void) opaque; /* unused */
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
}
|
||||
|
||||
|
||||
static bool bitmap_test_opaque(void *bitmap)
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *bitmap_get_buffer(void *bitmap)
|
||||
{
|
||||
assert(bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_destroy(void *bitmap)
|
||||
{
|
||||
assert(bitmap);
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_modified(void *bitmap)
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned char *load_file(const char *path, size_t *data_size)
|
||||
{
|
||||
FILE *fd;
|
||||
struct stat sb;
|
||||
unsigned char *buffer;
|
||||
size_t size;
|
||||
size_t n;
|
||||
|
||||
fd = fopen(path, "rb");
|
||||
if (!fd) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (stat(path, &sb)) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
size = sb.st_size;
|
||||
|
||||
buffer = malloc(size);
|
||||
if (!buffer) {
|
||||
fprintf(stderr, "Unable to allocate %lld bytes\n",
|
||||
(long long) size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
n = fread(buffer, 1, size, fd);
|
||||
if (n != size) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
*data_size = size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static void warning(const char *context, gif_result code)
|
||||
{
|
||||
fprintf(stderr, "%s failed: ", context);
|
||||
switch (code)
|
||||
{
|
||||
case GIF_INSUFFICIENT_FRAME_DATA:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_FRAME_DATA");
|
||||
break;
|
||||
case GIF_FRAME_DATA_ERROR:
|
||||
fprintf(stderr, "GIF_FRAME_DATA_ERROR");
|
||||
break;
|
||||
case GIF_INSUFFICIENT_DATA:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_DATA");
|
||||
break;
|
||||
case GIF_DATA_ERROR:
|
||||
fprintf(stderr, "GIF_DATA_ERROR");
|
||||
break;
|
||||
case GIF_INSUFFICIENT_MEMORY:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_MEMORY");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown code %i", code);
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void write_ppm(FILE* fh, const char *name, gif_animation *gif,
|
||||
bool no_write)
|
||||
{
|
||||
unsigned int i;
|
||||
gif_result code;
|
||||
|
||||
if (!no_write) {
|
||||
fprintf(fh, "P3\n");
|
||||
fprintf(fh, "# %s\n", name);
|
||||
fprintf(fh, "# width %u \n", gif->width);
|
||||
fprintf(fh, "# height %u \n", gif->height);
|
||||
fprintf(fh, "# frame_count %u \n", gif->frame_count);
|
||||
fprintf(fh, "# frame_count_partial %u \n", gif->frame_count_partial);
|
||||
fprintf(fh, "# loop_count %u \n", gif->loop_count);
|
||||
fprintf(fh, "%u %u 256\n", gif->width, gif->height * gif->frame_count);
|
||||
}
|
||||
|
||||
/* decode the frames */
|
||||
for (i = 0; i != gif->frame_count; i++) {
|
||||
unsigned int row, col;
|
||||
unsigned char *image;
|
||||
|
||||
code = gif_decode_frame(gif, i);
|
||||
if (code != GIF_OK)
|
||||
warning("gif_decode_frame", code);
|
||||
|
||||
if (!no_write) {
|
||||
fprintf(fh, "# frame %u:\n", i);
|
||||
image = (unsigned char *) gif->frame_image;
|
||||
for (row = 0; row != gif->height; row++) {
|
||||
for (col = 0; col != gif->width; col++) {
|
||||
size_t z = (row * gif->width + col) * 4;
|
||||
fprintf(fh, "%u %u %u ",
|
||||
(unsigned char) image[z],
|
||||
(unsigned char) image[z + 1],
|
||||
(unsigned char) image[z + 2]);
|
||||
}
|
||||
fprintf(fh, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gif_bitmap_callback_vt bitmap_callbacks = {
|
||||
bitmap_create,
|
||||
bitmap_destroy,
|
||||
bitmap_get_buffer,
|
||||
bitmap_set_opaque,
|
||||
bitmap_test_opaque,
|
||||
bitmap_modified
|
||||
};
|
||||
gif_animation gif;
|
||||
size_t size;
|
||||
gif_result code;
|
||||
unsigned char *data;
|
||||
FILE *outf = stdout;
|
||||
bool no_write = false;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s image.gif [out]\n", argv[0]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "If [out] is NOWRITE, the gif will be docoded "
|
||||
"but not output.\n");
|
||||
fprintf(stderr, "Otherwise [out] is an output filename.\n");
|
||||
fprintf(stderr, "When [out] is unset, output is to stdout.\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
if (strcmp(argv[2], "NOWRITE") == 0) {
|
||||
no_write = true;
|
||||
} else {
|
||||
outf = fopen(argv[2], "w+");
|
||||
if (outf == NULL) {
|
||||
fprintf(stderr, "Unable to open %s for writing\n", argv[2]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create our gif animation */
|
||||
gif_create(&gif, &bitmap_callbacks);
|
||||
|
||||
/* load file into memory */
|
||||
data = load_file(argv[1], &size);
|
||||
|
||||
/* begin decoding */
|
||||
do {
|
||||
code = gif_initialise(&gif, size, data);
|
||||
if (code != GIF_OK && code != GIF_WORKING) {
|
||||
warning("gif_initialise", code);
|
||||
gif_finalise(&gif);
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
} while (code != GIF_OK);
|
||||
|
||||
write_ppm(outf, argv[1], &gif, no_write);
|
||||
|
||||
if (argc > 2 && !no_write) {
|
||||
fclose(outf);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
gif_finalise(&gif);
|
||||
free(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
|
||||
# attempt to update our copy of libnsgif from the upstream repo
|
||||
|
||||
set -e
|
||||
|
||||
git clone git://git.netsurf-browser.org/libnsgif.git
|
||||
|
||||
echo copying out source files ...
|
||||
cp libnsgif/src/libnsgif.c .
|
||||
cp libnsgif/include/libnsgif.h .
|
||||
cp libnsgif/src/lzw.[ch] .
|
||||
cp libnsgif/src/utils/log.h utils
|
||||
|
||||
echo applying patches ...
|
||||
for patch in patches/*.patch; do
|
||||
patch -p0 <$patch
|
||||
done
|
||||
|
||||
echo cleaning up ...
|
||||
rm -rf libnsgif
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2003 James Bursa <bursa@users.sourceforge.net>
|
||||
* Copyright 2004 John Tytgat <John.Tytgat@aaug.net>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
* Licenced under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _LIBNSGIF_LOG_H_
|
||||
#define _LIBNSGIF_LOG_H_
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define LOG(x) ((void) 0)
|
||||
#else
|
||||
# define LOG(x) do { fprintf(stderr, x), fputc('\n', stderr); } while (0)
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#endif /* _LIBNSGIF_LOG_H_ */
|
|
@ -95,7 +95,7 @@ typedef struct _VipsForeignLoadNifti {
|
|||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadNiftiClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadNifti, vips_foreign_load_nifti,
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadNifti, vips_foreign_load_nifti,
|
||||
VIPS_TYPE_FOREIGN_LOAD );
|
||||
|
||||
static void
|
||||
|
|
|
@ -0,0 +1,948 @@
|
|||
/* load a GIF with libnsgif
|
||||
*
|
||||
* 6/10/18
|
||||
* - from gifload.c
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#define VERBOSE
|
||||
#define VIPS_DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/buf.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* - libnsgif does not seem to support comment metadata
|
||||
*
|
||||
* - it always loads the entire source file into memory
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* - hard to detect mono images -- local_colour_table in libnsgif is only set
|
||||
* when we decode a frame, so we can't tell just from init whether any
|
||||
* frames have colour info
|
||||
*
|
||||
* - don't bother detecting alpha -- if we can't detect RGB, alpha won't help
|
||||
* much
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_NSGIF
|
||||
|
||||
#include <libnsgif/libnsgif.h>
|
||||
|
||||
#define VIPS_TYPE_FOREIGN_LOAD_GIF (vips_foreign_load_nsgif_get_type())
|
||||
#define VIPS_FOREIGN_LOAD_GIF( obj ) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
|
||||
VIPS_TYPE_FOREIGN_LOAD_GIF, VipsForeignLoadNsgif ))
|
||||
#define VIPS_FOREIGN_LOAD_GIF_CLASS( klass ) \
|
||||
(G_TYPE_CHECK_CLASS_CAST( (klass), \
|
||||
VIPS_TYPE_FOREIGN_LOAD_GIF, VipsForeignLoadNsgifClass))
|
||||
#define VIPS_IS_FOREIGN_LOAD_GIF( obj ) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FOREIGN_LOAD_GIF ))
|
||||
#define VIPS_IS_FOREIGN_LOAD_GIF_CLASS( klass ) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FOREIGN_LOAD_GIF ))
|
||||
#define VIPS_FOREIGN_LOAD_GIF_GET_CLASS( obj ) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
|
||||
VIPS_TYPE_FOREIGN_LOAD_GIF, VipsForeignLoadNsgifClass ))
|
||||
|
||||
typedef struct _VipsForeignLoadNsgif {
|
||||
VipsForeignLoad parent_object;
|
||||
|
||||
/* Load this page (frame number).
|
||||
*/
|
||||
int page;
|
||||
|
||||
/* Load this many pages.
|
||||
*/
|
||||
int n;
|
||||
|
||||
/* Load from this source (set by subclasses).
|
||||
*/
|
||||
VipsSource *source;
|
||||
|
||||
/* The animation created by libnsgif.
|
||||
*/
|
||||
gif_animation *anim;
|
||||
|
||||
/* The data/size pair we pass to libnsgif.
|
||||
*/
|
||||
unsigned char *data;
|
||||
size_t size;
|
||||
|
||||
/* The frame_count, after we have removed undisplayable frames.
|
||||
*/
|
||||
int frame_count_displayable;
|
||||
|
||||
/* Delays between frames (in milliseconds). Array of length
|
||||
* @frame_count_displayable.
|
||||
*/
|
||||
int *delay;
|
||||
|
||||
/* A single centisecond value for compatibility.
|
||||
*/
|
||||
int gif_delay;
|
||||
|
||||
} VipsForeignLoadNsgif;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadNsgifClass;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadNsgif, vips_foreign_load_nsgif,
|
||||
VIPS_TYPE_FOREIGN_LOAD );
|
||||
|
||||
static const char *
|
||||
vips_foreign_load_nsgif_errstr( gif_result result )
|
||||
{
|
||||
switch( result ) {
|
||||
case GIF_WORKING:
|
||||
return( _( "Working" ) );
|
||||
|
||||
case GIF_OK:
|
||||
return( _( "OK" ) );
|
||||
|
||||
case GIF_INSUFFICIENT_FRAME_DATA:
|
||||
return( _( "Insufficient data to complete frame" ) );
|
||||
|
||||
case GIF_FRAME_DATA_ERROR:
|
||||
return( _( "GIF frame data error" ) );
|
||||
|
||||
case GIF_INSUFFICIENT_DATA:
|
||||
return( _( "Insufficient data to do anything" ) );
|
||||
|
||||
case GIF_DATA_ERROR:
|
||||
return( _( "GIF header data error" ) );
|
||||
|
||||
case GIF_INSUFFICIENT_MEMORY:
|
||||
return( _( "Insuficient memory to process" ) );
|
||||
|
||||
case GIF_FRAME_NO_DISPLAY:
|
||||
return( _( "No display" ) );
|
||||
|
||||
case GIF_END_OF_FRAME:
|
||||
return( _( "At end of frame" ) );
|
||||
|
||||
default:
|
||||
return( _( "Unknown error" ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_error( VipsForeignLoadNsgif *gif, gif_result result )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
|
||||
vips_error( class->nickname, "%s",
|
||||
vips_foreign_load_nsgif_errstr( result ) );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_dispose( GObject *gobject )
|
||||
{
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) gobject;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_dispose:\n" );
|
||||
|
||||
if( gif->anim ) {
|
||||
gif_finalise( gif->anim );
|
||||
VIPS_FREE( gif->anim );
|
||||
}
|
||||
VIPS_UNREF( gif->source );
|
||||
VIPS_FREE( gif->delay );
|
||||
|
||||
G_OBJECT_CLASS( vips_foreign_load_nsgif_parent_class )->
|
||||
dispose( gobject );
|
||||
}
|
||||
|
||||
static VipsForeignFlags
|
||||
vips_foreign_load_nsgif_get_flags_filename( const char *filename )
|
||||
{
|
||||
return( VIPS_FOREIGN_SEQUENTIAL );
|
||||
}
|
||||
|
||||
static VipsForeignFlags
|
||||
vips_foreign_load_nsgif_get_flags( VipsForeignLoad *load )
|
||||
{
|
||||
return( VIPS_FOREIGN_SEQUENTIAL );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_nsgif_is_a_source( VipsSource *source )
|
||||
{
|
||||
const unsigned char *data;
|
||||
|
||||
if( (data = vips_source_sniff( source, 4 )) &&
|
||||
data[0] == 'G' &&
|
||||
data[1] == 'I' &&
|
||||
data[2] == 'F' &&
|
||||
data[3] == '8' )
|
||||
return( TRUE );
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
static void
|
||||
print_frame( gif_frame *frame )
|
||||
{
|
||||
printf( "frame:\n" );
|
||||
printf( " display = %d\n", frame->display );
|
||||
printf( " frame_delay = %d\n", frame->frame_delay );
|
||||
printf( " virgin = %d\n", frame->virgin );
|
||||
printf( " opaque = %d\n", frame->opaque );
|
||||
printf( " redraw_required = %d\n", frame->redraw_required );
|
||||
printf( " disposal_method = %d\n", frame->disposal_method );
|
||||
printf( " transparency = %d\n", frame->transparency );
|
||||
printf( " transparency_index = %d\n", frame->transparency_index );
|
||||
printf( " redraw_x = %d\n", frame->redraw_x );
|
||||
printf( " redraw_y = %d\n", frame->redraw_y );
|
||||
printf( " redraw_width = %d\n", frame->redraw_width );
|
||||
printf( " redraw_height = %d\n", frame->redraw_height );
|
||||
}
|
||||
|
||||
static void
|
||||
print_animation( gif_animation *anim )
|
||||
{
|
||||
int i;
|
||||
|
||||
printf( "animation:\n" );
|
||||
printf( " width = %d\n", anim->width );
|
||||
printf( " height = %d\n", anim->height );
|
||||
printf( " frame_count = %d\n", anim->frame_count );
|
||||
printf( " frame_count_partial = %d\n", anim->frame_count_partial );
|
||||
printf( " decoded_frame = %d\n", anim->decoded_frame );
|
||||
printf( " frame_image = %p\n", anim->frame_image );
|
||||
printf( " loop_count = %d\n", anim->loop_count );
|
||||
printf( " frame_holders = %d\n", anim->frame_holders );
|
||||
printf( " background_index = %d\n", anim->background_index );
|
||||
printf( " colour_table_size = %d\n", anim->colour_table_size );
|
||||
printf( " global_colours = %d\n", anim->global_colours );
|
||||
printf( " global_colour_table = %p\n", anim->global_colour_table );
|
||||
printf( " local_colour_table = %p\n", anim->local_colour_table );
|
||||
|
||||
for( i = 0; i < anim->frame_holders; i++ ) {
|
||||
printf( "%d ", i );
|
||||
print_frame( &anim->frames[i] );
|
||||
}
|
||||
}
|
||||
#endif /*VERBOSE*/
|
||||
|
||||
static int
|
||||
vips_foreign_load_nsgif_set_header( VipsForeignLoadNsgif *gif,
|
||||
VipsImage *image )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_set_header:\n" );
|
||||
|
||||
vips_image_init_fields( image,
|
||||
gif->anim->width, gif->anim->height * gif->n, 4,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||
|
||||
if( vips_object_argument_isset( VIPS_OBJECT( gif ), "n" ) )
|
||||
vips_image_set_int( image,
|
||||
VIPS_META_PAGE_HEIGHT, gif->anim->height );
|
||||
vips_image_set_int( image, VIPS_META_N_PAGES,
|
||||
gif->frame_count_displayable );
|
||||
vips_image_set_int( image, "loop", gif->anim->loop_count );
|
||||
vips_image_set_array_int( image, "delay",
|
||||
gif->delay, gif->frame_count_displayable );
|
||||
|
||||
if( gif->anim->global_colours &&
|
||||
gif->anim->global_colour_table &&
|
||||
gif->anim->background_index >= 0 &&
|
||||
gif->anim->background_index < gif->anim->colour_table_size ) {
|
||||
int index = gif->anim->background_index;
|
||||
unsigned char *entry = (unsigned char *)
|
||||
&gif->anim->global_colour_table[index];
|
||||
|
||||
double array[3];
|
||||
|
||||
array[0] = entry[0];
|
||||
array[1] = entry[1];
|
||||
array[2] = entry[2];
|
||||
|
||||
vips_image_set_array_double( image, "background", array, 3 );
|
||||
}
|
||||
|
||||
VIPS_SETSTR( image->filename,
|
||||
vips_connection_filename( VIPS_CONNECTION( gif->source ) ) );
|
||||
|
||||
/* DEPRECATED "gif-loop"
|
||||
*
|
||||
* Not the correct behavior as loop=1 became gif-loop=0
|
||||
* but we want to keep the old behavior untouched!
|
||||
*/
|
||||
vips_image_set_int( image,
|
||||
"gif-loop", gif->anim->loop_count == 0 ?
|
||||
0 : gif->anim->loop_count - 1 );
|
||||
|
||||
/* The deprecated gif-delay field is in centiseconds.
|
||||
*/
|
||||
vips_image_set_int( image, "gif-delay", gif->gif_delay );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Scan the GIF as quickly as we can and extract transparency, bands, pages,
|
||||
* etc.
|
||||
*
|
||||
* Don't flag any errors unless we have to: we want to work for corrupt or
|
||||
* malformed GIFs.
|
||||
*
|
||||
* Close as soon as we can to free up the fd.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_load_nsgif_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) load;
|
||||
|
||||
const void *data;
|
||||
size_t size;
|
||||
gif_result result;
|
||||
int i;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_header:\n" );
|
||||
|
||||
/* We map in the image, then minimise to close any underlying file
|
||||
* object. This won't unmap.
|
||||
*/
|
||||
if( !(data = vips_source_map( gif->source, &size )) )
|
||||
return( -1 );
|
||||
vips_source_minimise( gif->source );
|
||||
|
||||
result = gif_initialise( gif->anim, size, (void *) data );
|
||||
VIPS_DEBUG_MSG( "gif_initialise() = %d\n", result );
|
||||
#ifdef VERBOSE
|
||||
print_animation( gif->anim );
|
||||
#endif /*VERBOSE*/
|
||||
if( result != GIF_OK &&
|
||||
result != GIF_WORKING &&
|
||||
result != GIF_INSUFFICIENT_FRAME_DATA ) {
|
||||
vips_foreign_load_nsgif_error( gif, result );
|
||||
return( -1 );
|
||||
}
|
||||
else if( result == GIF_INSUFFICIENT_FRAME_DATA &&
|
||||
load->fail ) {
|
||||
vips_error( class->nickname, "%s", _( "truncated GIF" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Many GIFs have dead frames at the end. Remove these from our count.
|
||||
*/
|
||||
for( i = gif->anim->frame_count - 1;
|
||||
i >= 0 && !gif->anim->frames[i].display; i-- )
|
||||
;
|
||||
gif->frame_count_displayable = i + 1;
|
||||
#ifdef VERBOSE
|
||||
if( gif->frame_count_displayable != gif->anim->frame_count )
|
||||
printf( "vips_foreign_load_nsgif_open: "
|
||||
"removed %d undisplayable frames\n",
|
||||
gif->anim->frame_count - gif->frame_count_displayable );
|
||||
#endif /*VERBOSE*/
|
||||
|
||||
if( !gif->frame_count_displayable ) {
|
||||
vips_error( class->nickname, "%s", _( "no frames in GIF" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( gif->n == -1 )
|
||||
gif->n = gif->frame_count_displayable - gif->page;
|
||||
|
||||
if( gif->page < 0 ||
|
||||
gif->n <= 0 ||
|
||||
gif->page + gif->n > gif->frame_count_displayable ) {
|
||||
vips_error( class->nickname, "%s", _( "bad page number" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* In ms, frame_delay in cs.
|
||||
*/
|
||||
VIPS_FREE( gif->delay );
|
||||
if( !(gif->delay = VIPS_ARRAY( NULL,
|
||||
gif->frame_count_displayable, int )) )
|
||||
return( -1 );
|
||||
for( i = 0; i < gif->frame_count_displayable; i++ )
|
||||
gif->delay[i] = 10 * gif->anim->frames[i].frame_delay;
|
||||
|
||||
gif->gif_delay = gif->anim->frames[0].frame_delay;
|
||||
|
||||
vips_foreign_load_nsgif_set_header( gif, load->out );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_nsgif_generate( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsRect *r = &or->valid;
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) a;
|
||||
|
||||
int y;
|
||||
|
||||
#ifdef VERBOSE
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_generate: "
|
||||
"top = %d, height = %d\n", r->top, r->height );
|
||||
#endif /*VERBOSE*/
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
/* The page for this output line, and the line number in page.
|
||||
*/
|
||||
int page = (r->top + y) / gif->anim->height + gif->page;
|
||||
int line = (r->top + y) % gif->anim->height;
|
||||
|
||||
gif_result result;
|
||||
VipsPel *p, *q;
|
||||
|
||||
g_assert( line >= 0 && line < gif->anim->height );
|
||||
g_assert( page >= 0 && page < gif->frame_count_displayable );
|
||||
|
||||
if( gif->anim->decoded_frame != page ) {
|
||||
result = gif_decode_frame( gif->anim, page );
|
||||
VIPS_DEBUG_MSG( " gif_decode_frame(%d) = %d\n",
|
||||
page, result );
|
||||
if( result != GIF_OK ) {
|
||||
vips_foreign_load_nsgif_error( gif, result );
|
||||
return( -1 );
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
print_animation( gif->anim );
|
||||
#endif /*VERBOSE*/
|
||||
}
|
||||
|
||||
p = gif->anim->frame_image +
|
||||
line * gif->anim->width * sizeof( int );
|
||||
q = VIPS_REGION_ADDR( or, 0, r->top + y );
|
||||
memcpy( q, p, VIPS_REGION_SIZEOF_LINE( or ) );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_nsgif_load( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) load;
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( load ), 4 );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_load:\n" );
|
||||
|
||||
/* Make the output pipeline.
|
||||
*/
|
||||
t[0] = vips_image_new();
|
||||
if( vips_foreign_load_nsgif_set_header( gif, t[0] ) )
|
||||
return( -1 );
|
||||
|
||||
/* Strips 8 pixels high to avoid too many tiny regions.
|
||||
*/
|
||||
if( vips_image_generate( t[0],
|
||||
NULL, vips_foreign_load_nsgif_generate, NULL, gif, NULL ) ||
|
||||
vips_sequential( t[0], &t[1],
|
||||
"tile_height", VIPS__FATSTRIP_HEIGHT,
|
||||
NULL ) ||
|
||||
vips_image_write( t[1], load->real ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_class_init( VipsForeignLoadNsgifClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_nsgif_dispose;
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "gifload_base";
|
||||
object_class->description = _( "load GIF with libnsgif" );
|
||||
|
||||
/* High priority, so that we handle vipsheader etc.
|
||||
*/
|
||||
foreign_class->priority = 50;
|
||||
|
||||
load_class->get_flags_filename =
|
||||
vips_foreign_load_nsgif_get_flags_filename;
|
||||
load_class->get_flags = vips_foreign_load_nsgif_get_flags;
|
||||
load_class->header = vips_foreign_load_nsgif_header;
|
||||
load_class->load = vips_foreign_load_nsgif_load;
|
||||
|
||||
VIPS_ARG_INT( class, "page", 10,
|
||||
_( "Page" ),
|
||||
_( "Load this page from the file" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadNsgif, page ),
|
||||
0, 100000, 0 );
|
||||
|
||||
VIPS_ARG_INT( class, "n", 6,
|
||||
_( "n" ),
|
||||
_( "Load this many pages" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadNsgif, n ),
|
||||
-1, 100000, 1 );
|
||||
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_foreign_load_nsgif_bitmap_create( int width, int height )
|
||||
{
|
||||
/* Enforce max GIF dimensions of 16383 (0x7FFF). This should be enough
|
||||
* for anyone, and will prevent the worst GIF bombs.
|
||||
*/
|
||||
if( width <= 0 ||
|
||||
width > 16383 ||
|
||||
height <= 0 ||
|
||||
height > 16383 ) {
|
||||
vips_error( "gifload",
|
||||
"%s", _( "bad image dimensions") );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return g_malloc0( (gsize) width * height * 4 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_bitmap_set_opaque( void *bitmap, bool opaque )
|
||||
{
|
||||
(void) opaque; /* unused */
|
||||
(void) bitmap; /* unused */
|
||||
g_assert( bitmap );
|
||||
}
|
||||
|
||||
static bool
|
||||
vips_foreign_load_nsgif_bitmap_test_opaque( void *bitmap )
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
g_assert( bitmap );
|
||||
|
||||
return( false );
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
vips_foreign_load_nsgif_bitmap_get_buffer( void *bitmap )
|
||||
{
|
||||
g_assert( bitmap );
|
||||
|
||||
return( bitmap );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_bitmap_destroy( void *bitmap )
|
||||
{
|
||||
g_assert( bitmap );
|
||||
g_free( bitmap );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_bitmap_modified( void *bitmap )
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
g_assert( bitmap );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static gif_bitmap_callback_vt vips_foreign_load_nsgif_bitmap_callbacks = {
|
||||
vips_foreign_load_nsgif_bitmap_create,
|
||||
vips_foreign_load_nsgif_bitmap_destroy,
|
||||
vips_foreign_load_nsgif_bitmap_get_buffer,
|
||||
vips_foreign_load_nsgif_bitmap_set_opaque,
|
||||
vips_foreign_load_nsgif_bitmap_test_opaque,
|
||||
vips_foreign_load_nsgif_bitmap_modified
|
||||
};
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_init( VipsForeignLoadNsgif *gif )
|
||||
{
|
||||
gif->anim = g_new0( gif_animation, 1 );
|
||||
gif_create( gif->anim, &vips_foreign_load_nsgif_bitmap_callbacks );
|
||||
gif->n = 1;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadNsgifFile {
|
||||
VipsForeignLoadNsgif parent_object;
|
||||
|
||||
/* Filename for load.
|
||||
*/
|
||||
char *filename;
|
||||
|
||||
} VipsForeignLoadNsgifFile;
|
||||
|
||||
typedef VipsForeignLoadNsgifClass VipsForeignLoadNsgifFileClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadNsgifFile, vips_foreign_load_nsgif_file,
|
||||
vips_foreign_load_nsgif_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_gif_file_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) object;
|
||||
VipsForeignLoadNsgifFile *file = (VipsForeignLoadNsgifFile *) object;
|
||||
|
||||
if( file->filename )
|
||||
if( !(gif->source =
|
||||
vips_source_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_nsgif_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static const char *vips_foreign_nsgif_suffs[] = {
|
||||
".gif",
|
||||
NULL
|
||||
};
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_nsgif_file_is_a( const char *filename )
|
||||
{
|
||||
VipsSource *source;
|
||||
gboolean result;
|
||||
|
||||
if( !(source = vips_source_new_from_file( filename )) )
|
||||
return( FALSE );
|
||||
result = vips_foreign_load_nsgif_is_a_source( source );
|
||||
VIPS_UNREF( source );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_file_class_init(
|
||||
VipsForeignLoadNsgifFileClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "gifload";
|
||||
object_class->description = _( "load GIF with libnsgif" );
|
||||
object_class->build = vips_foreign_load_gif_file_build;
|
||||
|
||||
foreign_class->suffs = vips_foreign_nsgif_suffs;
|
||||
|
||||
load_class->is_a = vips_foreign_load_nsgif_file_is_a;
|
||||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
_( "Filename to load from" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadNsgifFile, filename ),
|
||||
NULL );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_file_init( VipsForeignLoadNsgifFile *file )
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadNsgifBuffer {
|
||||
VipsForeignLoadNsgif parent_object;
|
||||
|
||||
/* Load from a buffer.
|
||||
*/
|
||||
VipsArea *blob;
|
||||
|
||||
} VipsForeignLoadNsgifBuffer;
|
||||
|
||||
typedef VipsForeignLoadNsgifClass VipsForeignLoadNsgifBufferClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadNsgifBuffer, vips_foreign_load_nsgif_buffer,
|
||||
vips_foreign_load_nsgif_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_nsgif_buffer_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) object;
|
||||
VipsForeignLoadNsgifBuffer *buffer =
|
||||
(VipsForeignLoadNsgifBuffer *) object;
|
||||
|
||||
if( buffer->blob &&
|
||||
!(gif->source = vips_source_new_from_memory(
|
||||
buffer->blob->data,
|
||||
buffer->blob->length )) )
|
||||
return( -1 );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_nsgif_buffer_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_nsgif_buffer_is_a_buffer( const void *buf, size_t len )
|
||||
{
|
||||
VipsSource *source;
|
||||
gboolean result;
|
||||
|
||||
if( !(source = vips_source_new_from_memory( buf, len )) )
|
||||
return( FALSE );
|
||||
result = vips_foreign_load_nsgif_is_a_source( source );
|
||||
VIPS_UNREF( source );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_buffer_class_init(
|
||||
VipsForeignLoadNsgifBufferClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "gifload_buffer";
|
||||
object_class->description = _( "load GIF with libnsgif" );
|
||||
object_class->build = vips_foreign_load_nsgif_buffer_build;
|
||||
|
||||
load_class->is_a_buffer = vips_foreign_load_nsgif_buffer_is_a_buffer;
|
||||
|
||||
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||
_( "Buffer" ),
|
||||
_( "Buffer to load from" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadNsgifBuffer, blob ),
|
||||
VIPS_TYPE_BLOB );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_buffer_init( VipsForeignLoadNsgifBuffer *buffer )
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadNsgifSource {
|
||||
VipsForeignLoadNsgif parent_object;
|
||||
|
||||
/* Load from a source.
|
||||
*/
|
||||
VipsSource *source;
|
||||
|
||||
} VipsForeignLoadNsgifSource;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadNsgifSourceClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadNsgifSource, vips_foreign_load_nsgif_source,
|
||||
vips_foreign_load_nsgif_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_nsgif_source_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadNsgif *gif = (VipsForeignLoadNsgif *) object;
|
||||
VipsForeignLoadNsgifSource *source =
|
||||
(VipsForeignLoadNsgifSource *) object;
|
||||
|
||||
if( source->source ) {
|
||||
gif->source = source->source;
|
||||
g_object_ref( gif->source );
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_nsgif_source_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_source_class_init(
|
||||
VipsForeignLoadNsgifSourceClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "gifload_source";
|
||||
object_class->description = _( "load gif from source" );
|
||||
object_class->build = vips_foreign_load_nsgif_source_build;
|
||||
|
||||
load_class->is_a_source = vips_foreign_load_nsgif_is_a_source;
|
||||
|
||||
VIPS_ARG_OBJECT( class, "source", 1,
|
||||
_( "Source" ),
|
||||
_( "Source to load from" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadNsgifSource, source ),
|
||||
VIPS_TYPE_SOURCE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_nsgif_source_init( VipsForeignLoadNsgifSource *source )
|
||||
{
|
||||
}
|
||||
|
||||
#endif /*HAVE_NSGIF*/
|
||||
|
||||
/**
|
||||
* vips_gifload:
|
||||
* @filename: file to load
|
||||
* @out: (out): output image
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @page: %gint, page (frame) to read
|
||||
* * @n: %gint, load this many pages
|
||||
*
|
||||
* Read a GIF file into a libvips image.
|
||||
*
|
||||
* Use @page to select a page to render, numbering from zero.
|
||||
*
|
||||
* Use @n to select the number of pages to render. The default is 1. Pages are
|
||||
* rendered in a vertical column. Set to -1 to mean "until the end of the
|
||||
* document". Use vips_grid() to change page layout.
|
||||
*
|
||||
* The output image is always RGBA.
|
||||
*
|
||||
* See also: vips_image_new_from_file().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_gifload( const char *filename, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "gifload", ap, filename, out );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_gifload_buffer:
|
||||
* @buf: (array length=len) (element-type guint8): memory area to load
|
||||
* @len: (type gsize): size of memory area
|
||||
* @out: (out): image to write
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @page: %gint, page (frame) to read
|
||||
* * @n: %gint, load this many pages
|
||||
*
|
||||
* Read a GIF-formatted memory block into a VIPS image. Exactly as
|
||||
* vips_gifload(), but read from a memory buffer.
|
||||
*
|
||||
* You must not free the buffer while @out is active. The
|
||||
* #VipsObject::postclose signal on @out is a good place to free.
|
||||
*
|
||||
* See also: vips_gifload().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_gifload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
VipsBlob *blob;
|
||||
int result;
|
||||
|
||||
/* We don't take a copy of the data or free it.
|
||||
*/
|
||||
blob = vips_blob_new( NULL, buf, len );
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "gifload_buffer", ap, blob, out );
|
||||
va_end( ap );
|
||||
|
||||
vips_area_unref( VIPS_AREA( blob ) );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_gifload_source:
|
||||
* @source: source to load
|
||||
* @out: (out): image to write
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* * @page: %gint, page (frame) to read
|
||||
* * @n: %gint, load this many pages
|
||||
*
|
||||
* Exactly as vips_gifload(), but read from a source.
|
||||
*
|
||||
* See also: vips_gifload().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_gifload_source( VipsSource *source, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "gifload_source", ap, source, out );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
|
@ -226,7 +226,11 @@ read_header( Read *read, VipsImage *out )
|
|||
VIPS_FORMAT_FLOAT,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_scRGB, 1.0, 1.0 );
|
||||
if( read->tiles )
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
/* Even though this is a tiled reader, we hint thinstrip
|
||||
* since with the cache we are quite happy serving that if
|
||||
* anything downstream would like it.
|
||||
*/
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
else
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||
}
|
||||
|
@ -363,7 +367,8 @@ vips__openexr_read( const char *filename, VipsImage *out )
|
|||
VipsImage *raw;
|
||||
VipsImage *t;
|
||||
|
||||
/* Tile cache: keep enough for two complete rows of tiles.
|
||||
/* Tile cache: keep enough for two complete rows of tiles,
|
||||
* plus 50%.
|
||||
*/
|
||||
raw = vips_image_new();
|
||||
vips_object_local( out, raw );
|
||||
|
@ -375,14 +380,11 @@ vips__openexr_read( const char *filename, VipsImage *out )
|
|||
read, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Copy to out, adding a cache. Enough tiles for a complete
|
||||
* row, plus 50%.
|
||||
*/
|
||||
if( vips_tilecache( raw, &t,
|
||||
"tile_width", read->tile_width,
|
||||
"tile_height", read->tile_height,
|
||||
"max_tiles", (int)
|
||||
(1.5 * (1 + raw->Xsize / read->tile_width)),
|
||||
(2.5 * (1 + raw->Xsize / read->tile_width)),
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( vips_image_write( t, out ) ) {
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -115,7 +115,7 @@ G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveTiff, vips_foreign_save_tiff,
|
|||
|
||||
#define UC VIPS_FORMAT_UCHAR
|
||||
|
||||
/* Type promotion for save ... just always go to uchar.
|
||||
/* Type promotion for jpeg-in-tiff save ... just always go to uchar.
|
||||
*/
|
||||
static int bandfmt_jpeg[10] = {
|
||||
/* UC C US S UI I F X D DX */
|
||||
|
|
|
@ -328,11 +328,18 @@ write_webp_anim( VipsWebPWrite *write, VipsImage *image, int page_height )
|
|||
|
||||
/* There might just be the old gif-delay field. This is centiseconds.
|
||||
*/
|
||||
gif_delay = 4;
|
||||
gif_delay = 10;
|
||||
if( vips_image_get_typeof( image, "gif-delay" ) &&
|
||||
vips_image_get_int( image, "gif-delay", &gif_delay ) )
|
||||
return( -1 );
|
||||
|
||||
/* Force frames with a small or no duration to 100ms
|
||||
* to be consistent with web browsers and other
|
||||
* transcoding tools.
|
||||
*/
|
||||
if( gif_delay <= 1 )
|
||||
gif_delay = 10;
|
||||
|
||||
/* New images have an array of ints instead.
|
||||
*/
|
||||
delay = NULL;
|
||||
|
@ -371,7 +378,8 @@ write_webp_anim( VipsWebPWrite *write, VipsImage *image, int page_height )
|
|||
page_index = top / page_height;
|
||||
if( delay &&
|
||||
page_index < delay_length )
|
||||
timestamp_ms += delay[page_index];
|
||||
timestamp_ms += delay[page_index] <= 10 ?
|
||||
100 : delay[page_index];
|
||||
else
|
||||
timestamp_ms += gif_delay * 10;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ pkginclude_HEADERS = \
|
|||
mosaicing.h \
|
||||
create.h \
|
||||
video.h \
|
||||
cimg_funcs.h \
|
||||
object.h \
|
||||
private.h \
|
||||
rect.h \
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/* cimg_funcs.h
|
||||
*
|
||||
* 20/9/09
|
||||
* - from proto.h
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IM_CIMG_FUNCS_H
|
||||
#define IM_CIMG_FUNCS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
int vips_gmic( VipsImage **in, VipsImage **out, int n,
|
||||
int padding, double x_scale, double y_scale, const char *command, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#endif /*IM_CIMG_FUNCS_H*/
|
|
@ -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
|
||||
|
|
|
@ -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 ); \
|
||||
|
|
|
@ -92,7 +92,7 @@ G_STMT_START { \
|
|||
(void) g_once( ONCE, FUNC, CLIENT ); \
|
||||
} G_STMT_END
|
||||
|
||||
/* VIPS_RINT() does "bankers rounding", it rounds to the nerarest even integer.
|
||||
/* VIPS_RINT() does "bankers rounding", it rounds to the nearest even integer.
|
||||
* For things like image geometry, we want strict nearest int.
|
||||
*
|
||||
* If you know it's unsigned, _UINT is a little faster.
|
||||
|
|
|
@ -153,7 +153,6 @@ extern "C" {
|
|||
#include <vips/draw.h>
|
||||
#include <vips/create.h>
|
||||
#include <vips/video.h>
|
||||
#include <vips/cimg_funcs.h>
|
||||
|
||||
/* We can't use _ here since this will be compiled by our clients and they may
|
||||
* not have _().
|
||||
|
|
|
@ -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*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -801,12 +801,11 @@ static void
|
|||
vips_image_add_progress( VipsImage *image )
|
||||
{
|
||||
if( vips__progress ||
|
||||
g_getenv( "VIPS_PROGRESS" )
|
||||
#if ENABLE_DEPRECATED
|
||||
g_getenv( "VIPS_PROGRESS" ) ||
|
||||
g_getenv( "IM_PROGRESS" ) ) {
|
||||
#else
|
||||
g_getenv( "VIPS_PROGRESS" ) ) {
|
||||
|| g_getenv( "IM_PROGRESS" )
|
||||
#endif
|
||||
) {
|
||||
|
||||
/* Keep the %complete we displayed last time here.
|
||||
*/
|
||||
|
@ -1676,14 +1675,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 );
|
||||
}
|
||||
|
@ -2514,12 +2506,11 @@ vips_get_disc_threshold( void )
|
|||
*/
|
||||
threshold = 100 * 1024 * 1024;
|
||||
|
||||
if( (env = g_getenv( "VIPS_DISC_THRESHOLD" ))
|
||||
#if ENABLE_DEPRECATED
|
||||
if( (env = g_getenv( "VIPS_DISC_THRESHOLD" )) ||
|
||||
(env = g_getenv( "IM_DISC_THRESHOLD" )) )
|
||||
#else
|
||||
if( (env = g_getenv( "VIPS_DISC_THRESHOLD" )) )
|
||||
|| (env = g_getenv( "IM_DISC_THRESHOLD" ))
|
||||
#endif
|
||||
)
|
||||
threshold = vips__parse_size( env );
|
||||
|
||||
if( vips__disc_threshold )
|
||||
|
|
|
@ -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();
|
||||
|
@ -467,12 +449,11 @@ vips_init( const char *argv0 )
|
|||
g_free( locale );
|
||||
bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
|
||||
|
||||
if( g_getenv( "VIPS_INFO" )
|
||||
#if ENABLE_DEPRECATED
|
||||
if( g_getenv( "VIPS_INFO" ) ||
|
||||
g_getenv( "IM_INFO" ) )
|
||||
#else
|
||||
if( g_getenv( "VIPS_INFO" ) )
|
||||
|| g_getenv( "IM_INFO" )
|
||||
#endif
|
||||
)
|
||||
vips_verbose();
|
||||
if( g_getenv( "VIPS_PROFILE" ) )
|
||||
vips_profile_set( TRUE );
|
||||
|
@ -586,27 +567,14 @@ vips_init( const char *argv0 )
|
|||
* set up if you are using libvips from something like Ruby. Allow this
|
||||
* env var hack as a workaround.
|
||||
*/
|
||||
if( g_getenv( "VIPS_WARNING" )
|
||||
#if ENABLE_DEPRECATED
|
||||
if( g_getenv( "VIPS_WARNING" ) ||
|
||||
g_getenv( "IM_WARNING" ) )
|
||||
#else
|
||||
if( g_getenv( "VIPS_WARNING" ) )
|
||||
|| g_getenv( "IM_WARNING" )
|
||||
#endif
|
||||
)
|
||||
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 +1025,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 +1036,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 +1145,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 +1155,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" ) ) {
|
||||
|
@ -564,8 +565,6 @@ vips_source_new_from_options( const char *options )
|
|||
*
|
||||
* Loaders should call this in response to the minimise signal on their output
|
||||
* image.
|
||||
*
|
||||
* Returns: 0 on success, or -1 on error.
|
||||
*/
|
||||
void
|
||||
vips_source_minimise( VipsSource *source )
|
||||
|
|
|
@ -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 )*/
|
||||
|
@ -406,13 +406,11 @@ vips_concurrency_get( void )
|
|||
*/
|
||||
if( vips__concurrency > 0 )
|
||||
nthr = vips__concurrency;
|
||||
else if( ((str = g_getenv( "VIPS_CONCURRENCY" ))
|
||||
#if ENABLE_DEPRECATED
|
||||
else if( ((str = g_getenv( "VIPS_CONCURRENCY" )) ||
|
||||
(str = g_getenv( "IM_CONCURRENCY" ))) &&
|
||||
#else
|
||||
else if( (str = g_getenv( "VIPS_CONCURRENCY" )) &&
|
||||
|| (str = g_getenv( "IM_CONCURRENCY" ))
|
||||
#endif
|
||||
(x = atoi( str )) > 0 )
|
||||
) && (x = atoi( str )) > 0 )
|
||||
nthr = x;
|
||||
else
|
||||
nthr = get_num_processors();
|
||||
|
|
|
@ -900,6 +900,21 @@ transform_array_int_g_string( const GValue *src_value, GValue *dest_value )
|
|||
g_value_set_string( dest_value, vips_buf_all( &buf ) );
|
||||
}
|
||||
|
||||
static void
|
||||
transform_array_int_save_string( const GValue *src_value, GValue *dest_value )
|
||||
{
|
||||
GValue intermediate = { 0 };
|
||||
|
||||
g_value_init( &intermediate, G_TYPE_STRING );
|
||||
|
||||
transform_array_int_g_string( src_value, &intermediate );
|
||||
|
||||
vips_value_set_save_string( dest_value,
|
||||
g_value_get_string( &intermediate ) );
|
||||
|
||||
g_value_unset( &intermediate );
|
||||
}
|
||||
|
||||
/* It'd be great to be able to write a generic string->array function, but
|
||||
* it doesn't seem possible.
|
||||
*/
|
||||
|
@ -951,6 +966,21 @@ transform_g_string_array_int( const GValue *src_value, GValue *dest_value )
|
|||
g_free( str );
|
||||
}
|
||||
|
||||
static void
|
||||
transform_save_string_array_int( const GValue *src_value, GValue *dest_value )
|
||||
{
|
||||
GValue intermediate = { 0 };
|
||||
|
||||
g_value_init( &intermediate, G_TYPE_STRING );
|
||||
|
||||
g_value_set_string( &intermediate,
|
||||
vips_value_get_save_string( src_value ) );
|
||||
|
||||
transform_g_string_array_int( &intermediate, dest_value );
|
||||
|
||||
g_value_unset( &intermediate );
|
||||
}
|
||||
|
||||
/* We need a arrayint, we have an int, make a one-element array.
|
||||
*/
|
||||
static void
|
||||
|
@ -1006,6 +1036,10 @@ vips_array_int_get_type( void )
|
|||
transform_double_array_int );
|
||||
g_value_register_transform_func( VIPS_TYPE_ARRAY_DOUBLE, type,
|
||||
transform_array_double_array_int );
|
||||
g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
|
||||
transform_array_int_save_string );
|
||||
g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
|
||||
transform_save_string_array_int );
|
||||
}
|
||||
|
||||
return( type );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -102,12 +102,11 @@ vips_vector_init( void )
|
|||
/* Look for the environment variable VIPS_NOVECTOR and use that to turn
|
||||
* off as well.
|
||||
*/
|
||||
if( g_getenv( "VIPS_NOVECTOR" )
|
||||
#if ENABLE_DEPRECATED
|
||||
if( g_getenv( "VIPS_NOVECTOR" ) ||
|
||||
g_getenv( "IM_NOVECTOR" ) )
|
||||
#else
|
||||
if( g_getenv( "VIPS_NOVECTOR" ) )
|
||||
|| g_getenv( "IM_NOVECTOR" )
|
||||
#endif
|
||||
)
|
||||
vips__vector_enabled = FALSE;
|
||||
|
||||
#endif /*HAVE_ORC*/
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -54,10 +54,6 @@
|
|||
|
||||
#include "templates.h"
|
||||
|
||||
#ifdef WITH_DMALLOC
|
||||
#include <dmalloc.h>
|
||||
#endif /*WITH_DMALLOC*/
|
||||
|
||||
#define VIPS_TYPE_INTERPOLATE_BICUBIC \
|
||||
(vips_interpolate_bicubic_get_type())
|
||||
#define VIPS_INTERPOLATE_BICUBIC( obj ) \
|
||||
|
|
|
@ -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,
|
||||
|
@ -685,6 +700,10 @@ vips_thumbnail_build( VipsObject *object )
|
|||
in = t[12];
|
||||
}
|
||||
|
||||
/* Note the interpretation we will revert to after linear.
|
||||
*/
|
||||
input_interpretation = in->Type;
|
||||
|
||||
/* In linear mode, we need to transform to a linear space before
|
||||
* vips_resize().
|
||||
*/
|
||||
|
@ -719,11 +738,6 @@ vips_thumbnail_build( VipsObject *object )
|
|||
*/
|
||||
VipsInterpretation interpretation;
|
||||
|
||||
/* Note the interpretation we will revert to after
|
||||
* linear.
|
||||
*/
|
||||
input_interpretation = in->Type;
|
||||
|
||||
if( in->Bands < 3 )
|
||||
interpretation = VIPS_INTERPRETATION_GREY16;
|
||||
else
|
||||
|
@ -877,13 +891,13 @@ vips_thumbnail_build( VipsObject *object )
|
|||
thumbnail->export_profile );
|
||||
if( vips_colourspace( in, &t[7],
|
||||
VIPS_INTERPRETATION_XYZ, NULL ) ||
|
||||
vips_icc_export( t[7], &t[8],
|
||||
vips_icc_export( t[7], &t[10],
|
||||
"output_profile",
|
||||
thumbnail->export_profile,
|
||||
"intent", thumbnail->intent,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[8];
|
||||
in = t[10];
|
||||
}
|
||||
}
|
||||
else if( thumbnail->linear ) {
|
||||
|
@ -1113,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).
|
||||
|
@ -1133,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,
|
||||
|
@ -1326,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).
|
||||
|
@ -1522,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).
|
||||
|
|
|
@ -2,11 +2,9 @@ cplusplus/include/vips/VConnection8.h
|
|||
cplusplus/include/vips/VError8.h
|
||||
cplusplus/include/vips/VImage8.h
|
||||
cplusplus/include/vips/VInterpolate8.h
|
||||
cplusplus/include/vips/vips-operators.h
|
||||
libvips/include/vips/arithmetic.h
|
||||
libvips/include/vips/basic.h
|
||||
libvips/include/vips/buf.h
|
||||
libvips/include/vips/cimg_funcs.h
|
||||
libvips/include/vips/colour.h
|
||||
libvips/include/vips/connection.h
|
||||
libvips/include/vips/conversion.h
|
||||
|
@ -237,7 +235,6 @@ libvips/foreign/fits.c
|
|||
libvips/foreign/fitsload.c
|
||||
libvips/foreign/fitssave.c
|
||||
libvips/foreign/foreign.c
|
||||
libvips/foreign/gifload.c
|
||||
libvips/foreign/heifload.c
|
||||
libvips/foreign/heifsave.c
|
||||
libvips/foreign/jpeg2vips.c
|
||||
|
@ -254,6 +251,7 @@ libvips/foreign/matrixload.c
|
|||
libvips/foreign/matrixsave.c
|
||||
libvips/foreign/niftiload.c
|
||||
libvips/foreign/niftisave.c
|
||||
libvips/foreign/nsgifload.c
|
||||
libvips/foreign/openexr2vips.c
|
||||
libvips/foreign/openexrload.c
|
||||
libvips/foreign/openslide2vips.c
|
||||
|
@ -285,6 +283,8 @@ libvips/foreign/vipssave.c
|
|||
libvips/foreign/webp2vips.c
|
||||
libvips/foreign/webpload.c
|
||||
libvips/foreign/webpsave.c
|
||||
libvips/foreign/libnsgif/libnsgif.c
|
||||
libvips/foreign/libnsgif/lzw.c
|
||||
libvips/freqfilt/freqfilt.c
|
||||
libvips/freqfilt/freqmult.c
|
||||
libvips/freqfilt/fwfft.c
|
||||
|
@ -333,6 +333,7 @@ libvips/iofuncs/sinkmemory.c
|
|||
libvips/iofuncs/sinkscreen.c
|
||||
libvips/iofuncs/source.c
|
||||
libvips/iofuncs/sourcecustom.c
|
||||
libvips/iofuncs/sourceginput.c
|
||||
libvips/iofuncs/system.c
|
||||
libvips/iofuncs/target.c
|
||||
libvips/iofuncs/targetcustom.c
|
||||
|
|
|
@ -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,
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
@ -1,5 +1,4 @@
|
|||
# vim: set fileencoding=utf-8 :
|
||||
import filecmp
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
|
@ -18,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
|
||||
|
@ -38,7 +37,7 @@ class TestForeign:
|
|||
cls.cmyk.remove("icc-profile-data")
|
||||
|
||||
im = pyvips.Image.new_from_file(GIF_FILE)
|
||||
cls.onebit = im > 128
|
||||
cls.onebit = im[1] > 128
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
|
@ -681,10 +680,14 @@ class TestForeign:
|
|||
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
w1 = x1.webpsave_buffer(Q=10)
|
||||
|
||||
# our test gif has delay 0 for the first frame set in error,
|
||||
# when converting to WebP this should result in a 100ms delay.
|
||||
expected_delay = [100 if d <= 10 else d for d in x1.get("delay")]
|
||||
|
||||
x2 = pyvips.Image.new_from_buffer(w1, "", n=-1)
|
||||
assert x1.width == x2.width
|
||||
assert x1.height == x2.height
|
||||
assert x1.get("delay") == x2.get("delay")
|
||||
assert expected_delay == x2.get("delay")
|
||||
assert x1.get("page-height") == x2.get("page-height")
|
||||
assert x1.get("gif-loop") == x2.get("gif-loop")
|
||||
|
||||
|
@ -800,61 +803,53 @@ class TestForeign:
|
|||
def test_gifload(self):
|
||||
def gif_valid(im):
|
||||
a = im(10, 10)
|
||||
assert_almost_equal_objects(a, [33])
|
||||
assert_almost_equal_objects(a, [33, 33, 33, 255])
|
||||
assert im.width == 159
|
||||
assert im.height == 203
|
||||
assert im.bands == 1
|
||||
assert im.bands == 4
|
||||
|
||||
self.file_loader("gifload", GIF_FILE, gif_valid)
|
||||
self.buffer_loader("gifload_buffer", GIF_FILE, gif_valid)
|
||||
|
||||
# 'n' param added in 8.5
|
||||
if pyvips.at_least_libvips(8, 5):
|
||||
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=2)
|
||||
assert x2.height == 2 * x1.height
|
||||
page_height = x2.get("page-height")
|
||||
assert page_height == x1.height
|
||||
# test metadata
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
# our test gif has delay 0 for the first frame set in error
|
||||
assert x2.get("delay") == [0, 50, 50, 50, 50]
|
||||
assert x2.get("loop") == 32760
|
||||
assert x2.get("background") == [255, 255, 255]
|
||||
# test deprecated fields too
|
||||
assert x2.get("gif-loop") == 32759
|
||||
assert x2.get("gif-delay") == 0
|
||||
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
assert x2.height == 5 * x1.height
|
||||
# our test gif has delay 0 for the first frame set in error
|
||||
assert x2.get("delay") == [0, 50, 50, 50, 50]
|
||||
# test every pixel
|
||||
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_EXPECTED_PNG_FILE)
|
||||
assert (x1 - x2).abs().max() == 0
|
||||
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, page=1, n=-1)
|
||||
assert x2.height == 4 * x1.height
|
||||
# test page handling
|
||||
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=2)
|
||||
assert x2.height == 2 * x1.height
|
||||
page_height = x2.get("page-height")
|
||||
assert page_height == x1.height
|
||||
|
||||
animation = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
filename = temp_filename(self.tempdir, '.png')
|
||||
animation.write_to_file(filename)
|
||||
# Uncomment to see output file
|
||||
# animation.write_to_file('cogs.png')
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
|
||||
assert x2.height == 5 * x1.height
|
||||
|
||||
assert filecmp.cmp(GIF_ANIM_EXPECTED_PNG_FILE, filename, shallow=False)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, page=1, n=-1)
|
||||
assert x2.height == 4 * x1.height
|
||||
|
||||
@skip_if_no("gifload")
|
||||
def test_gifload_animation_dispose_background(self):
|
||||
animation = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_FILE, n=-1)
|
||||
|
||||
filename = temp_filename(self.tempdir, '.png')
|
||||
animation.write_to_file(filename)
|
||||
|
||||
# Uncomment to see output file
|
||||
# animation.write_to_file('dispose-background.png')
|
||||
|
||||
assert filecmp.cmp(GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, filename, shallow=False)
|
||||
x1 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_FILE, n=-1)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE)
|
||||
assert (x1 - x2).abs().max() == 0
|
||||
|
||||
@skip_if_no("gifload")
|
||||
def test_gifload_animation_dispose_previous(self):
|
||||
animation = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_FILE, n=-1)
|
||||
|
||||
filename = temp_filename(self.tempdir, '.png')
|
||||
animation.write_to_file(filename)
|
||||
|
||||
# Uncomment to see output file
|
||||
# animation.write_to_file('dispose-previous.png')
|
||||
|
||||
assert filecmp.cmp(GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, filename, shallow=False)
|
||||
x1 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_FILE, n=-1)
|
||||
x2 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE)
|
||||
assert (x1 - x2).abs().max() == 0
|
||||
|
||||
@skip_if_no("svgload")
|
||||
def test_svgload(self):
|
||||
|
@ -1132,6 +1127,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()
|
||||
|
|
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