Merge branch 'master' into add-libnsgif

This commit is contained in:
John Cupitt 2020-06-29 23:07:13 +01:00
commit 345fee4917
313 changed files with 23466 additions and 12679 deletions

23
.editorconfig Normal file
View File

@ -0,0 +1,23 @@
# http://editorconfig.org
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = true
[*.{cpp,c,h}]
indent_style = tab
indent_size = 8
[*.py]
indent_style = space
indent_size = 4
[Makefile.am]
indent_style = tab
indent_size = 8
[configure.ac]
indent_style = space
indent_size = 2

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
open_collective: libvips

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.pytest_cache
compile
.pytest_cache
a.out

View File

@ -1,118 +1,50 @@
language: cpp
before_script:
- $PYTHON -m pip download --no-deps https://github.com/libvips/pyvips/archive/$PYVIPS_VERSION.tar.gz
- tar xf $PYVIPS_VERSION.tar.gz
- $PYTHON -m pip install --user --upgrade pyvips-$PYVIPS_VERSION/[test]
- ./autogen.sh
--disable-dependency-tracking
--with-jpeg-includes=$JPEG/include
--with-jpeg-libraries=$JPEG/lib
--with-magick=$WITH_MAGICK
- make -j$JOBS -s
script:
- make -j$JOBS -s -k V=0 VERBOSE=1 check
- LD_LIBRARY_PATH=$PWD/libvips/.libs
DYLD_LIBRARY_PATH=$PWD/libvips/.libs
LD_PRELOAD=$ASAN_DSO
$PYTHON -m pytest -v test/test-suite
matrix:
allow_failures:
- os: osx
fast_finish: true
include:
- os: linux
sudo: required
dist: xenial
compiler: gcc
env:
- PYTHON=python2
- PYVIPS_VERSION=master
- JPEG=/usr
- JOBS=`nproc`
- WITH_MAGICK=yes
cache: ccache
- os: linux
sudo: required
dist: xenial
compiler: clang
env:
- PYTHON=python2
- PYVIPS_VERSION=master
- JPEG=/usr
- JOBS=`nproc`
- WITH_MAGICK=no
- CFLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fopenmp -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
- LDFLAGS="-fsanitize=address,undefined -dynamic-asan -fopenmp=libiomp5"
- ASAN_DSO=/usr/local/clang-7.0.0/lib/clang/7.0.0/lib/linux/libclang_rt.asan-x86_64.so
- LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/lsan.supp"
- UBSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/ubsan.supp"
# comment these out, I get strange parse errors from asan for some
# reason
#
# ASAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/asan.supp"
install:
# add support for WebP
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebp-dev_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebpdemux2_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebpmux3_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebp6_0.6.1-2_amd64.deb
- sudo dpkg -i *.deb
cache: ccache
- os: osx
osx_image: xcode10.1
env:
- PYTHON=python2
- PYVIPS_VERSION=master
- JPEG=/usr/local
- JOBS="`sysctl -n hw.ncpu`"
- WITH_MAGICK=yes
- PATH="/usr/local/opt/ccache/libexec:$PATH"
- HOMEBREW_NO_AUTO_UPDATE=1
cache: ccache
env:
global:
- PYTHON=python3
- PYVIPS_VERSION=master
addons:
apt:
update: true
sources:
sources: &common_sources
# use a more recent imagemagick instead of 6.8.9-9
- sourceline: 'ppa:opencpu/imagemagick'
- sourceline: 'ppa:cran/imagemagick'
# add support for HEIF files
- sourceline: 'ppa:strukturag/libheif'
- sourceline: 'ppa:strukturag/libde265'
packages:
- automake
- gtk-doc-tools
packages: &common_packages
- automake
- gtk-doc-tools
- gobject-introspection
- libfftw3-dev
- libexif-dev
- python3-pip
- python3-setuptools
- python3-wheel
- libfftw3-dev
- libexif-dev
- libjpeg-turbo8-dev
- libpng12-dev
- libpng12-dev
- libwebp-dev
# missing on xenial, unfortunately
# - libwebpmux2
- libtiff5-dev
- libtiff5-dev
- libheif-dev
- libexpat1-dev
- libmagick++-dev
- bc
- libmagick++-dev
- libcfitsio3-dev
- libgsl0-dev
- libgsl0-dev
- libmatio-dev
- liborc-0.4-dev
- liblcms2-dev
- libpoppler-glib-dev
- librsvg2-dev
- librsvg2-dev
- libgif-dev
- libopenexr-dev
- libpango1.0-dev
- libgsf-1-dev
- libpango1.0-dev
- libgsf-1-dev
- libopenslide-dev
- libffi-dev
- libiomp-dev
homebrew:
packages:
- ccache
@ -120,6 +52,7 @@ addons:
- gobject-introspection
- fftw
- libexif
- libjpeg-turbo
- webp
- imagemagick
- cfitsio
@ -133,3 +66,91 @@ addons:
- pango
- libgsf
- openslide
jobs:
allow_failures:
- os: osx
fast_finish: true
include:
- os: linux
sudo: required
dist: xenial
compiler: gcc
env:
- JPEG=/usr
- JOBS=`nproc`
- WITH_MAGICK=yes
cache: ccache
- os: linux
sudo: required
dist: xenial
compiler: clang
addons:
apt:
sources:
- *common_sources
- sourceline: deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main
key_url: https://apt.llvm.org/llvm-snapshot.gpg.key
packages:
- *common_packages
- clang-10
- libomp-10-dev
env:
- JPEG=/usr
- JOBS=`nproc`
- WITH_MAGICK=no
- LDSHARED="clang -shared"
- CFLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fopenmp -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
- LDFLAGS="-fsanitize=address,undefined -shared-libasan -fopenmp=libomp"
- ASAN_DSO=`clang-10 -print-file-name=libclang_rt.asan-x86_64.so`
- ASAN_SYMBOLIZER_PATH=`which llvm-symbolizer-10`
- ASAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/asan.supp"
- LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/lsan.supp"
- UBSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/suppressions/ubsan.supp"
- LD_LIBRARY_PATH="`dirname $ASAN_DSO`:/usr/lib/llvm-10/lib:$LD_LIBRARY_PATH"
- DLCLOSE_PRELOAD="$TRAVIS_BUILD_DIR/dlclose.so"
install:
# add support for WebP
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebp-dev_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebpdemux2_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebpmux3_0.6.1-2_amd64.deb
- wget http://archive.ubuntu.com/ubuntu/pool/main/libw/libwebp/libwebp6_0.6.1-2_amd64.deb
- sudo dpkg -i *.deb
# switch to Clang 10 using update-alternatives
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 100
--slave /usr/bin/clang++ clang++ /usr/bin/clang++-10
# workaround for https://github.com/google/sanitizers/issues/89
# otherwise libIlmImf-2_2.so ends up as <unknown module>
- echo -e '#include <stdio.h>\nint dlclose(void*handle){return 0;}' | clang -shared -xc -odlclose.so -
cache: ccache
- os: osx
osx_image: xcode11
env:
- JPEG=/usr/local/opt/jpeg-turbo
- JOBS="`sysctl -n hw.ncpu`"
- WITH_MAGICK=yes
- PATH="/usr/local/opt/ccache/libexec:$PATH"
- PKG_CONFIG_PATH="/usr/local/opt/jpeg-turbo/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig:$PKG_CONFIG_PATH"
- HOMEBREW_NO_AUTO_UPDATE=1
- CC="gcc-9"
- CXX="g++-9"
cache: ccache
before_script:
- $PYTHON -m pip download --no-deps https://github.com/libvips/pyvips/archive/$PYVIPS_VERSION.tar.gz
- tar xf $PYVIPS_VERSION.tar.gz
- $PYTHON -m pip install --user --upgrade pyvips-$PYVIPS_VERSION/[test]
- ./autogen.sh
--disable-dependency-tracking
--disable-deprecated
--with-jpeg-includes=$JPEG/include
--with-jpeg-libraries=$JPEG/lib
--with-magick=$WITH_MAGICK
- make -j$JOBS -s
script:
- make -j$JOBS -s -k V=0 VERBOSE=1 check
- LD_LIBRARY_PATH=$PWD/libvips/.libs
DYLD_LIBRARY_PATH=$PWD/libvips/.libs
LD_PRELOAD="$ASAN_DSO $DLCLOSE_PRELOAD"
$PYTHON -m pytest -sv --log-cli-level=WARNING test/test-suite

66
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,66 @@
libvips Code of Conduct
=======================
libvips, is developed and maintained by a mixed group of professionals and
volunteers from all over the world.
We ask people to adhere to a few ground rules. They apply equally to founders,
maintainers, contributors and those seeking help and guidance.
This is not meant to be an exhaustive list of things you are not allowed to do.
We rather would like you to think of it as a guide to enrich our community and
the technical community in general with new knowledge and perspectives by
allowing everyone to participate.
This code of conduct applies to all spaces managed by the libvips
community. This includes the mailing list, our GitHub projects, face to face
events, and any other forums created by the community for communication
within the community. In addition, violations of this code outside these
spaces may also affect a person's ability to participate within them.
If you believe someone is violating the code of conduct, we ask that you
report it.
- **Be friendly and patient.**
- **Be welcoming.** We strive to be a community that welcomes and supports
people of all backgrounds.
- **Be considerate.** Your work will be used by other people, and you in turn
will depend on the work of others. Any decision you take will affect users
and colleagues, and you should take those consequences into account when
making decisions. Remember that we're a world-wide community, so you might
not be communicating in someone else's primary language.
- **Be respectful.** Not all of us will agree all the time, but disagreement
is no excuse for poor behavior and poor manners. We might all experience
some frustration now and then, but we cannot allow that frustration to turn
into a personal attack. Its important to remember that a community where
people feel uncomfortable or threatened is not a productive one. Members of
our community should be respectful when dealing with other members as
well as with people outside the our community.
- **Be careful in the words that you choose.** We are a community of
professionals, and we conduct ourselves professionally. Be kind to others.
Do not insult or put down other participants. Harassment and other
exclusionary behavior aren't acceptable. This includes, but is not limited
to:
- Violent threats or language directed against another person.
- Discriminatory jokes and language.
- Posting sexually explicit or violent material.
- Posting (or threatening to post) other people's personally identifying
information ("doxing").
- Personal insults, especially those using racist or sexist terms.
- Unwelcome sexual attention.
- Advocating for, or encouraging, any of the above behavior.
- Repeated harassment of others. In general, if someone asks you to stop,
then stop.
- **When we disagree, try to understand why.** Disagreements, both social and
technical, happen all the time. It is important that we resolve
disagreements and differing views constructively. Remember that were
different. The strength of group software development comes from its
varied community, people from a wide range of backgrounds. Different
people have different perspectives on issues. Being unable to understand
why someone holds a viewpoint doesnt mean that theyre wrong. Dont
forget we all make mistakes and blaming each other doesnt get us
anywhere. Instead, focus on helping to resolve issues and learning
from mistakes.
Text based on the Code of Conduct of the [Django
community](https://www.djangoproject.com/conduct/).

View File

@ -1,3 +1,68 @@
24/1/20 started 8.10.0
- more conformat IIIF output from dzsave [regisrob]
- add @id to dzsave to set IIIF id property [regisrob]
- add max and min to region shrink [rgluskin]
- allow \ as an escape character in vips_break_token() [akemrir]
- tiffsave has a "depth" param to set max pyr depth
- libtiff LOGLUV images load and save as libvips XYZ
- add gifload_source, csvload_source, csvsave_target, matrixload_source,
matrixsave_source, pdfload_source, heifload_source, heifsave_target,
ppmload_source, ppmsave_target
- revise vipsthumbnail flags
- add VIPS_LEAK env var
- add vips_pipe_read_limit_set(), --vips-pipe-read-limit,
VIPS_PIPE_READ_LIMIT
- revise gifload to fix BACKGROUND and PREVIOUS dispose [alon-ne]
- add subsample_mode, deprecate no_subsample in jpegsave [Elad-Laufer]
- add vips_isdirf()
- add PAGENUMBER support to tiff write [jclavoie-jive]
- add "all" mode to smartcrop
- flood fill could stop half-way for some very complex shapes
- better handling of unaligned reads in multipage tiffs [petoor]
- add experimental libspng reader
- mark old --delete option to vipsthumbnail as deprecated [UweOhse]
- png save with a bad ICC profile just gives a warning
- add "premultipled" option to vips_affine(), clarified vips_resize()
behaviour with alpha channels
- improve bioformats support with read and write of tiff subifd pyramids
- thumbnail exploits subifd pyramids
- handle all EXIF orientation cases, deprecate
vips_autorot_get_angle() [Elad-Laufer]
- load PNGs with libspng, if possible
- deprecate heifload autorotate -- it's now always on
- revised resize improves accuracy [kleisauke]
- add --vips-config flag to show configuration info
- add "bitdepth" param to tiff save, deprecate "squash" [MathemanFlo]
- tiff load and save now supports 2 and 4 bit data [MathemanFlo]
- pngsave @bitdepth parameter lets you write 1, 2 and 4 bit PNGs
- ppmsave also uses "bitdepth" now, for consistency
- reduce operation cache max to 100
- rework the final bits of vips7 for vips8 [kleisauke]
- --disable-deprecated now works [kleisauke]
- vipsheader allows "stdin" as a filename
24/4/20 started 8.9.3
- better iiif tile naming [IllyaMoskvin]
31/1/19 started 8.9.2
- fix a deadlock with --vips-leak [DarthSim]
- better gifload behaviour for DISPOSAL_UNSPECIFIED [DarthSim]
- ban ppm max_value < 0
- add fuzz corpus to dist
- detect read errors correctly in source_sniff
- fix regression in autorot [malomalo]
- thumbnail on HEIC images could select the thumbnail incorrectly under some
size modes [ZorinArsenij]
20/6/19 started 8.9.1
- don't use the new source loaders for new_from_file or new_from_buffer, it
will break the loader priority system
- fix thumbnail autorot [janko]
- fix a warning with magicksave with no delay array [chregu]
- fix a race in tiled tiff load [kleisauke]
- better imagemagick init [LebronCurry]
- lock for metadata changes [jcupitt]
20/6/19 started 8.9.0
- add vips_image_get/set_array_int()
- disable webp alpha output if all frame fill the canvas and are solid
@ -16,6 +81,21 @@
- add @interpretation and @format to rawload
- nifti load/save uses double for all floating point metadata
- add vips_error_buffer_copy()
- add VipsSource and VipsTarget: a universal IO class for loaders and savers
- jpeg, png, tiff (though not tiffsave), rad, svg, ppm and webp use the
new IO class
- rewritten ppm load/save is faster and uses less memory
- add @no_strip option to dzsave [kalozka1]
- add iiif layout to dzsave
- fix use of resolution-unit metadata on tiff save [kayarre]
- support TIFF CIELAB images with alpha [angelmixu]
- support TIFF with premultiplied alpha in any band
- block metadata changes on shared images [pvdz]
- RGB and sRGB are synonmous
17/9/19 started 8.8.4
- improve compatibility with older imagemagick versions
- remove realpath, since it can fail on systems with grsec
31/8/19 started 8.8.3
- revert sharpen restoring the input colourspace

View File

@ -14,8 +14,7 @@ EXTRA_DIST = \
autogen.sh \
vips.pc.in \
vips-cpp.pc.in \
libvips.supp \
lsan.supp \
suppressions \
depcomp \
README.md

136
README.md
View File

@ -1,9 +1,56 @@
# libvips : an image processing library
[![Build Status](https://travis-ci.org/libvips/libvips.svg?branch=master)](https://travis-ci.org/libvips/libvips)
[![OSS-fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libvips.png)](https://oss-fuzz.com/coverage-report/job/libfuzzer_asan_libvips/latest)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libvips.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=2&q=proj:libvips)
[![Coverity Status](https://scan.coverity.com/projects/6503/badge.svg)](https://scan.coverity.com/projects/jcupitt-libvips)
# This branch
Is for experiemtning with [libspng](https://github.com/randy408/libspng).
## Notes
Build libspng:
```
cd libspng
meson build --prefix=/home/john/vips --libdir=/home/john/vips/lib \
--buildtype=release
cd build
ninja
ninja install
```
Installs `spng.pc`.
Sample code:
https://github.com/randy408/libspng/blob/master/examples/example.c
libspng benchmark:
```
$ time vips avg wtc.png
117.065766
real 0m2.972s
user 0m3.376s
sys 0m0.197s
```
And for libpng:
```
$ time vips avg wtc.png
117.065766
real 0m3.816s
user 0m4.177s
sys 0m0.221s
```
# Introduction
libvips is a [demand-driven, horizontally
threaded](https://github.com/libvips/libvips/wiki/Why-is-libvips-quick)
image processing library. Compared to similar
@ -67,7 +114,7 @@ Untar, then in the libvips directory you should just be able to do:
./configure
Check the summary at the end of `configure` carefully. libvips must have
`build-essential`, `pkg-config`, `glib2.0-dev`, `libexpat1-dev`.
`build-essential`, `pkg-config`, `libglib2.0-dev`, `libexpat1-dev`.
You'll need the dev packages for the file format support you want. For basic
jpeg and tiff support, you'll need `libtiff5-dev`, `libjpeg-turbo8-dev`,
@ -89,7 +136,6 @@ Run the test suite with:
Run a specific test with:
pytest --verbose
pytest test/test-suite/test_foreign.py -k test_tiff
# Building libvips from git
@ -103,7 +149,7 @@ and `gobject-introspection`, see the dependencies section below. For example:
brew install gtk-doc
Then build the build system with:
Then generate the build system with:
./autogen.sh --prefix=/home/john/vips
@ -114,62 +160,12 @@ Debug build:
make
make install
Leak check. Use the suppressions file `supp/valgrind.supp`.
export G_DEBUG=gc-friendly
valgrind --suppressions=vips-x.y.z/supp/valgrind.supp \
--leak-check=yes \
vips ... > vips-vg.log 2>&1
Memory error debug:
valgrind --vgdb=yes --vgdb-error=0 vips ...
valgrind threading check:
valgrind --tool=helgrind vips ... > vips-vg.log 2>&1
Clang build:
CC=clang CXX=clang++ ./configure --prefix=/home/john/vips
Clang static analysis:
scan-build ./configure --disable-introspection --disable-debug
scan-build -o scan -v make
scan-view scan/2013-11-22-2
Clang dynamic analysis:
FLAGS="-g -O1 -fno-omit-frame-pointer"
CC=clang CXX=clang++ LD=clang \
CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" LDFLAGS=-fsanitize=address \
./configure --prefix=/home/john/vips
FLAGS="-O1 -g -fsanitize=thread"
FLAGS="$FLAGS -fPIC"
FLAGS="$FLAGS -fno-omit-frame-pointer -fno-optimize-sibling-calls"
CC=clang CXX=clang++ LD=clang \
CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \
LDFLAGS="-fsanitize=thread -fPIC" \
./configure --prefix=/home/john/vips \
--without-magick \
--disable-introspection
G_DEBUG=gc-friendly vips copy ~/pics/k2.jpg x.jpg >& log
Build with the GCC auto-vectorizer and diagnostics (or just -O3):
FLAGS="-O2 -march=native -ffast-math"
FLAGS="$FLAGS -ftree-vectorize -fdump-tree-vect-details"
CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \
./configure --prefix=/home/john/vips
# Dependencies
libvips has to have `glib2.0-dev` and `libexpat1-dev`. Other dependencies
are optional, see below.
libvips has to have `libglib2.0-dev` and `libexpat1-dev`. Other dependencies
are optional.
# Optional dependencies
## Optional dependencies
If suitable versions are found, libvips will add support for the following
libraries automatically. See `./configure --help` for a set of flags to
@ -284,7 +280,7 @@ If available, vips can load and save WebP images.
### libniftiio
If available, vips can load and save NIFTI images.
If available, vips can load and save NIfTI images.
### OpenEXR
@ -300,9 +296,25 @@ files: Aperio, Hamamatsu, Leica, MIRAX, Sakura, Trestle, and Ventana.
If available, libvips can load and save HEIC images.
# Disclaimer
# Contributors
No guarantees of performance accompany this software, nor is any
responsibility assumed on the part of the authors. Please read the licence
agreement.
### Code Contributors
This project exists thanks to all the people who contribute.
<a href="https://github.com/libvips/libvips/graphs/contributors"><img src="https://opencollective.com/libvips/contributors.svg?width=890&button=false" /></a>
### Organizations
Support this project with your organization. Your logo will show up here with a link to your website.
<a href="https://opencollective.com/libvips/organization/0/website"><img src="https://opencollective.com/libvips/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/1/website"><img src="https://opencollective.com/libvips/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/2/website"><img src="https://opencollective.com/libvips/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/3/website"><img src="https://opencollective.com/libvips/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/4/website"><img src="https://opencollective.com/libvips/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/5/website"><img src="https://opencollective.com/libvips/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/6/website"><img src="https://opencollective.com/libvips/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/7/website"><img src="https://opencollective.com/libvips/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/8/website"><img src="https://opencollective.com/libvips/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/libvips/organization/9/website"><img src="https://opencollective.com/libvips/organization/9/avatar.svg"></a>

439
TODO
View File

@ -1,439 +0,0 @@
- try
$ vips gaussmat x.mat 0.1 0.1
(vips:28376): GLib-GObject-WARNING **: value "-1" of type 'gint' is invalid or out of range for property 'width' of type 'gint'
(vips:28376): GLib-GObject-WARNING **: value "-1" of type 'gint' is invalid or out of range for property 'height' of type 'gint'
$ more x.mat
1 1 0 0
5.55604e+180
check numeric range of SIGMA args, we should standardize
- rewind should break more things ... does it remove upsteam/downstream? does it
just need to remove reorder links?
perhaps reorder should use upstream/downstream, then it will be broken anyway
- not sure about utf8 error messages on win
- strange:
$ vips similarity --scale 0.33 k2.jpg x.v
$ vipsheader k2.jpg
k2.jpg: 1450x2048 uchar, 3 bands, srgb, jpegload
$ vipsheader x.v
x.v: 478x676 uchar, 3 bands, srgb, jpegload
1450 * 0.33 = 478.5 ... this was rounded down
2048 * 0.33 = 675.84 ... this was rounded up
- add APPROX convsep test?
- add more webp tests to py suite
- try moving some more of the CLI tests to py
- colour needs to split _build() into preprocess / process / postprocess
phases
in icc_import, for example, we want to check that the supplied profile is
compatible with the input image as it will be when unpacked and ready for
process_line
see vips_image_expected_bands() in icc_transform.c for the current hacky
solution
- use the incremental webp decoding api to support seq for webp images
https://developers.google.com/speed/webp/docs/api#decodingadvancedapi
doesn't seem to be possible
- does ruby need to unpack RefString as well? what about C++?
- are the mosaic functions calling vips_fastcor()? it must be very slow
add vips_fastcor_direct()
nope .. it's im_chkpair.c:im_correl()
im_extract_area(main)
im_extract_area(sub)
im_extract_band(main)
im_extract_band(sub)
im_spcor(sub)
im_maxpos(sub)
then im__chkpair() runs that 20 times, then loops ... oh dear
- perhaps im_maxpos_subpel() / im_minpos_subpel() should be undeprecated,
useful with vips_fastcor()
- why can't we do
im = Vips.Image.new_from_file("/data/john/pics/k2.jpg", access = "sequential")
no idea ... this works fine:
im.embed(10, 10, 100, 100, extend = "copy")
test:
op = Vips.Operation.new("embed")
op.props.__setattr__("extend", "copy")
op = Vips.Operation.new("jpegload")
op.props.__setattr__("access", "sequential")
first setattr works fine, second fails with invalid literal
- test other cpp arg types
input int works
input double
input enum works
input image works
input doublevec
input imagevec
input blob
output int
output double works
output enum
output image works
output doublevec
output imagevec
output blob
we probably need to unpack the ink back to double before blending
- ink to vec etc must have a way to give a complex constant
eg. drawink needs a --ink_imag option with the imaginary components of the
ink
look for uses of vips__vector_to_ink() and add extra params to other places
too, eg. vips_embed(), vips_insert() etc.
- vips__ink_to_vector() needs an optional imag return
- vips_getpoint() needs an optional imag return
- add porter-duff compositing, see
https://github.com/libvips/ruby-vips/issues/28
- now vips_linear() has uchar output, can we do something with orc?
- do restrict on some more packages, we've just done arithmetic so far
also resample, colour, some of conversion, create,
- maybe avg?
but avg doesn't subclass arithmetic, so we can't
- for interpolate, we'd need to be able to unroll the vector, so the
interpolator would need to be built for the bands / stride / type of the
image
need new API For this since interpolators currently work for any image
- vips_gaussblur() should switch to float prec if given a float image?
same for vips_conv()?
maybe precision is a dumb thing
- support --strip for other writers
- vipsthumbnail could shrink-on-load openslide and pyr tiff as well?
we have "shrink" for jpegload, move this into the base loader
support it for tiff and openslide as well
use it from nip2 for zooming? only if the partial flag is set though, we
don't want to use it on jpg files
- quadratic doesn't work for order 3
start to get jaggies on lines --- the 3rd differential isn't being
initialised correctly for the sub-region?
seems fine vertically, only get errors on horizontal tile boundaries
because we step across tiles left to right: y doesn't change, only x does
not sure it works for order 2 either, we are seeing interpolation errors
on image edges
mosaic
======
- balance should use new meta stuff
- histogram balance option?
resample
========
- check mosaic1, global_balance, similarity etc. use of im__affine
how can we move them to im_affinei ?
- perspective transform with a matrix ... base it on the Lenz transformer, but
partial
foreign
=======
- magick2vips should spot ICC profiles and attach them as meta
- interlaced jpg needs massive memory, we should have two jpg read modes, like
png
- add more sequential mode readers
$ grep -l write_line *.c
csv.c
matlab.c
openexr2vips.c
ppm.c
radiance.c
- foreign docs come up as "VipsForeignSave", annoying, why?
- add nifti support
http://niftilib.sourceforge.net/
- add matlab write
- im_exr2vips can now use c++ api
see TODO notes in openexr read (though they all need more openexr C API)
consider openexr write
- magick should set some header field for n_frames and frame_height? see also
analyze
- im_csv2vips() could use "-" for filename to mean stdin
but then we'd have to read to a malloced buffer of some sort rather than an
image, since we might need to grow it during the read, since we couldn't
then seek
packaging
=========
- test _O_TEMPORARY thing on Windows
convolution
===========
- revisit orc conv
use an 8.8 accumulator ... build the scale into the 8.8 coeffs ... no div at
the end, just a shift
need 8 x 8.8 -> 8.8 for each coeff though
- im_conv()/im_morph() could have more than 10 programs? try 20 and see if we
still have a speedup
make a base class for vector area operations with a matrix with three vfuncs
for init / generate code for one element / end and a gslist of programs, use
that as the base for morph and conv
wait for vipsobject for this
- we have aconv and aconvsep
test timing, make sure it;s worth having a separate aconvsep version
if it is, make im_aconvsep an optimisation: call im_aconvsep_raw() from
vips_conv() if mask width or height == 1 and prec == APPROX
now we can get rid of im_aconvsep() since it's just vips_convsep() with prec
set to approx
aconv needs some more work, get it going at least with gaussian
arithmetic
==========
- HAVE_HYPOT could define a hypot() macro?
- fix a better NaN policy
should we not generate images containing NaN (eg. divide tries to avoid /0),
or should vips_max() etc. try to avoid NaN in images (eg. vips_max() takes a
lot a care to skip NaN, though vips_stats() does not)?
iofuncs
=======
- need vips_image_invalidate_area()
- look at libpeas for plugin support
http://live.gnome.org/Libpeas
- how about
vips max add[babe.jpg,babe2.jpg]
does that make any sense?
vips copy add[babe.jpg,add[babe2.jpg,babe3.jpg]] sum.v
perhaps use curly brackets for code?
vips max add{babe.jpg,babe2.jpg}
no brackets or square brackets for options
- transform_g_string_array_image() can't handle quoted strings, so filenames
with spaces will break
is there an easy fix? can we reuse code from the csv parser?
the csv parser just parses FILE* streams, we'd need to break it out
- note member free stuff in vipsobject docs
should boxed get freed in finalise rather than dispose?
vipsobject has few docs atm :(
- vips_object_set_argument_from_string() needs more arg types
must be some way to make this more automatic
- generate the code for vips_add() etc. automatically? it might be
nice to have them all in one place at least
- what does G_UNLIKELY() do? can we use it?
- look into G_GNUC_DEPRECATED for back compat in vips8
- should im_rwcheck() copy to disc?
maybe im_rwcheck_disc() copies to im->filename and maps that
rather awkward to do atm with the way check.c is structured
swig
====
- swig is not wrapping im_project() correctly ... returns an extra VImage via
a param
- doc strings would be nice, read the SWIG notes on this
new bindings
============
- new binding is still missing constants
how do boxed types work? confusing
we need to be able to make a VipsArrayDouble
- Vips.Image has members like chain, __subclasshook__ etc etc, are we
really subclassing it correctly?
- add __add__ etc overloads
freq_filt
=========
- fft with odd width or height is broken ... DC ends up in the wrong place
libvipsCC
=========
- need new C++ API
- need an im_init_world() for C++ which does cmd-line args too, so C++ progs
can get --vips-progress and stuff automatically
tools
=====
- need a way to make the vips.1 etc. man pages
gtk has things like docs/reference/gtk/gtk-update-icon-cache.xml and man
pages are made from that with xslt
- get rid of a lot of the command-line programs, who wants to write a man page
for batch_image_convert etc yuk
- can we make man pages for the API as well? probably not from googling a bit
- rename header, edvips as vipsheader, vipsedit
maybe have back compat links?
new operations
==============
- bilateral filtering, see:
http://en.wikipedia.org/wiki/Bilateral_filter
http://www.shellandslate.com/fastmedian.html
http://people.csail.mit.edu/sparis/bf_course/
also a mail from Martin Breidt has links to several fast free C
implementations
- http://en.wikipedia.org/wiki/Otsu%27s_method
- non-linear sharpen: replace each pixel by the lightest or darkest neighbour
depending on which is closer in value
- look at
There is an order 1 algorithm for doing medians over boxes (truly O(1)
per pixel: I checked it carefully; it's like doing means over boxes in
order 1 per pixel) in OpenCV since February 2012 I think, due to
Perreault (and Hebert).
It appears to be well respected, at least for 8-bit medians. Very
memory intensive. Simple and elegant. No clue if it fits VIPS well
(probably not?).
Article: nomis80.org/ctmf.pdf
- see
http://www.dentistry.bham.ac.uk/landinig/software/cdeconv/cdeconv.html
http://www.nature.com/srep/2015/150730/srep12096/full/srep12096.html
sounds useful for BM?

View File

@ -61,4 +61,6 @@ autoheader
$LIBTOOLIZE --copy --force --automake
automake --add-missing --copy
./configure $*
if test -z "$NOCONFIGURE"; then
./configure $*
fi

View File

@ -2,7 +2,7 @@
# also update the version number in the m4 macros below
AC_INIT([vips], [8.9.0], [vipsip@jiscmail.ac.uk])
AC_INIT([vips], [8.10.0], [vipsip@jiscmail.ac.uk])
# required for gobject-introspection
AC_PREREQ(2.62)
@ -17,7 +17,7 @@ AC_CONFIG_MACRO_DIR([m4])
# user-visible library versioning
m4_define([vips_major_version], [8])
m4_define([vips_minor_version], [9])
m4_define([vips_minor_version], [10])
m4_define([vips_micro_version], [0])
m4_define([vips_version],
[vips_major_version.vips_minor_version.vips_micro_version])
@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date -u -r ChangeLog`
# binary interface changes not backwards compatible?: reset age to 0
LIBRARY_CURRENT=54
LIBRARY_REVISION=0
LIBRARY_REVISION=3
LIBRARY_AGE=12
# patched into include/vips/version.h
@ -450,33 +450,12 @@ 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.])])
# have to have these
# need glib 2.6 for GOption
PKG_CHECK_MODULES(REQUIRED, glib-2.0 >= 2.6 gmodule-2.0 gobject-2.0)
PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0"
# from 2.12 we have g_base64_encode()
PKG_CHECK_MODULES(BASE64_ENCODE, glib-2.0 >= 2.12,
[AC_DEFINE(HAVE_BASE64_ENCODE,1,
[define if your glib has g_base64_encode().]
)
],
[:
]
)
# from 2.14 we have g_option_context_get_help()
PKG_CHECK_MODULES(CONTEXT_GET_HELP, glib-2.0 >= 2.14,
[AC_DEFINE(HAVE_CONTEXT_GET_HELP,1,
[define if your glib has g_option_context_get_help().]
)
],
[:
]
)
# have to have these parts of glib ... we need glib 2.15 for gio
PKG_CHECK_MODULES(REQUIRED, glib-2.0 >= 2.15 gmodule-2.0 gobject-2.0 gio-2.0)
PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0"
# from 2.28 we have a monotonic timer
PKG_CHECK_MODULES(MONOTONIC, glib-2.0 >= 2.28,
PKG_CHECK_MODULES(MONOTONIC_TIME, glib-2.0 >= 2.28,
[AC_DEFINE(HAVE_MONOTONIC_TIME,1,
[define if your glib has g_get_monotonic_time().]
)
@ -485,11 +464,18 @@ PKG_CHECK_MODULES(MONOTONIC, glib-2.0 >= 2.28,
]
)
# the old threading system
PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
PACKAGES_USED="$PACKAGES_USED gthread-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().]
)
],
[:
]
)
# from 2.32 there are a new set of thread functions, annoyingly
# from 2.32 there are a new set of thread functions, it is no longer
# necessary to use g_thread_init() or to link against libgthread
PKG_CHECK_MODULES(THREADS, glib-2.0 >= 2.32,
[AC_DEFINE(HAVE_MUTEX_INIT,1,[define if your glib has g_mutex_init().])
AC_DEFINE(HAVE_COND_INIT,1,[define if your glib has g_cond_init().])
@ -498,6 +484,9 @@ PKG_CHECK_MODULES(THREADS, glib-2.0 >= 2.32,
AC_DEFINE(HAVE_VALUE_GET_SCHAR,1,
[define if your glib has g_value_get_schar().]
)
],
[PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
PACKAGES_USED="$PACKAGES_USED gthread-2.0"
]
)
@ -553,9 +542,16 @@ PKG_CHECK_MODULES(HAVE_CHECKED_MUL, glib-2.0 >= 2.48,
# check for gtk-doc
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
# we need expat ... we'd love to use expat.pc, but sadly this is only available
# for recent linuxes, so we have to use the old and horrible expat.m4
AM_WITH_EXPAT
# we need expat ... the .pc file for expat is only available
# for recent linuxes, so we fall back to AM_WITH_EXPAT
PKG_CHECK_MODULES(EXPAT, expat,
[expat_found=yes
PACKAGES_USED="$PACKAGES_USED expat"
],
[AM_WITH_EXPAT
]
)
if test x"$expat_found" = x"no"; then
exit 1
fi
@ -699,6 +695,16 @@ if test x"$magick6" = x"yes"; then
]
)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[#include <magick/api.h>],
[ColorspaceType colorspace = HCLpColorspace]
)],
[AC_DEFINE(HAVE_HCLPCOLORSPACE,1,
[define if your Magick has HCLpColorspace.])
]
)
# GetImageMagick() takes two args under GM, three under IM
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
@ -778,6 +784,19 @@ if test x"$with_orc" != x"no"; then
)
fi
# orc 0.4.30+ works with cf-protection, but 0.4.30 has a bug with multiple
# definitions of OrcTargetPowerPCFlags, so insist on 0.4.31
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.]
)
],
[:
]
)
fi
# lcms ... refuse to use lcms1
AC_ARG_WITH([lcms],
AS_HELP_STRING([--without-lcms], [build without lcms (default: test)]))
@ -836,14 +855,16 @@ if test x"$with_heif" != x"no"; then
PKG_CHECK_MODULES(HEIF, libheif,
[with_heif=yes
have_h265_decoder=`$PKG_CONFIG libheif --variable builtin_h265_decoder`
have_avif_decoder=`$PKG_CONFIG libheif --variable builtin_avif_decoder`
# test for !=no so that we work for older libheif which does not have
# this variable
if test x"$have_h265_decoder" != x"no"; then
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.])
fi
have_h265_encoder=`$PKG_CONFIG libheif --variable builtin_h265_encoder`
if test x"$have_h265_encoder" != x"no"; then
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.])
fi
@ -853,6 +874,8 @@ if test x"$with_heif" != x"no"; then
with_heif=no
have_h265_decoder=
have_h265_encoder=
have_avif_decoder=
have_avif_encoder=
]
)
fi
@ -905,16 +928,16 @@ if test x"$with_heif" = x"yes"; then
LIBS="$save_LIBS"
fi
# fetch untransformed width/height added in 1.3.4
# heif_decoding_options.convert_hdr_to_8bit added in 1.7.0
if test x"$with_heif" = x"yes"; then
save_LIBS="$LIBS"
LIBS="$LIBS $HEIF_LIBS"
AC_CHECK_FUNCS(heif_image_handle_get_ispe_width,[
AC_DEFINE(HAVE_HEIF_IMAGE_HANDLE_GET_ISPE_WIDTH,1,
[define if you have heif_image_handle_get_ispe_width.])
],[]
)
LIBS="$save_LIBS"
save_CFLAGS="$CFLAGS"
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])
],[],
[#include <libheif/heif.h>])
CFLAGS="$save_CFLAGS"
fi
# pdfium
@ -1176,6 +1199,21 @@ fi
)
#fi
# Look for libspng first
AC_ARG_WITH([libspng],
AS_HELP_STRING([--without-libspng], [build without libspng (default: test)]))
if test x"$with_libspng" != x"no"; then
PKG_CHECK_MODULES(SPNG, spng >= 0.6,
[AC_DEFINE(HAVE_SPNG,1,[define if you have libspng installed.])
with_libspng=yes
PACKAGES_USED="$PACKAGES_USED spng"
],
[with_libspng=no
]
)
fi
# look for PNG with pkg-config ... fall back to our tester
AC_ARG_WITH([png],
AS_HELP_STRING([--without-png], [build without libpng (default: test)]))
@ -1298,23 +1336,21 @@ if test x"$LIB_FUZZING_ENGINE" = x; then
LIB_FUZZING_ENGINE="libstandaloneengine.a"
fi
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
# sort includes to get longer, more specific dirs first
# helps, for example, selecting graphicsmagick over imagemagick
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $JPEG_CFLAGS $PNG_CFLAGS $IMAGEQUANT_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $LIBWEBPMUX_CFLAGS $LIBNSGIF_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $PDFIUM_INCLUDES $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS $HEIF_CFLAGS
do
echo $i
done | sort -ru`
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
# 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 $LIBNSGIF_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $PDFIUM_INCLUDES $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 $PNG_LIBS $IMAGEQUANT_LIBS $TIFF_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $EXPAT_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $LIBNSGIF_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_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 $LIBNSGIF_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"
# 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, 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 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, file import/export with libspng: $with_libspng, file import/export with libnsgif: $with_libnsgif"
AC_SUBST(VIPS_LIBDIR)
AC_SUBST(VIPS_CFLAGS)
AC_SUBST(VIPS_INCLUDES)
AC_SUBST(VIPS_LIBS)
AC_SUBST(VIPS_CONFIG)
AC_SUBST(PACKAGES_USED)
AC_SUBST(EXTRA_LIBS_USED)
@ -1333,6 +1369,7 @@ AC_OUTPUT([
libvips/Makefile
libvips/arithmetic/Makefile
libvips/colour/Makefile
libvips/colour/profiles/Makefile
libvips/conversion/Makefile
libvips/convolution/Makefile
libvips/deprecated/Makefile
@ -1365,6 +1402,7 @@ AC_OUTPUT([
fuzz/Makefile
])
# also add any new items to VIPS_CONFIG above
AC_MSG_RESULT([dnl
* build options
native win32: $vips_os_win32
@ -1393,7 +1431,7 @@ 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 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
@ -1403,6 +1441,8 @@ 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

View File

@ -11,6 +11,7 @@ lib_LTLIBRARIES = libvips-cpp.la
libvips_cpp_la_SOURCES = \
VImage.cpp \
VInterpolate.cpp \
VConnection.cpp \
VError.cpp
libvips_cpp_la_LDFLAGS = \

178
cplusplus/VConnection.cpp Normal file
View File

@ -0,0 +1,178 @@
/* Object part of the VSource and VTarget class
*/
/*
Copyright (C) 1991-2001 The National Gallery
This program 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <vips/vips8>
#include <vips/debug.h>
/*
#define VIPS_DEBUG
#define VIPS_DEBUG_VERBOSE
*/
VIPS_NAMESPACE_START
VSource
VSource::new_from_descriptor( int descriptor )
{
VipsSource *input;
if( !(input = vips_source_new_from_descriptor( descriptor )) )
throw VError();
VSource out( input );
return( out );
}
VSource
VSource::new_from_file( const char *filename )
{
VipsSource *input;
if( !(input = vips_source_new_from_file( filename )) )
throw VError();
VSource out( input );
return( out );
}
VSource
VSource::new_from_blob( VipsBlob *blob )
{
VipsSource *input;
if( !(input = vips_source_new_from_blob( blob )) )
throw VError();
VSource out( input );
return( out );
}
VSource
VSource::new_from_memory( const void *data,
size_t size )
{
VipsSource *input;
if( !(input = vips_source_new_from_memory( data, size )) )
throw VError();
VSource out( input );
return( out );
}
VSource
VSource::new_from_options( const char *options )
{
VipsSource *input;
if( !(input = vips_source_new_from_options( options )) )
throw VError();
VSource out( input );
return( out );
}
VOption *
VOption::set( const char *name, const VSource value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_SOURCE );
g_value_set_object( &pair->value, value.get_source() );
options.push_back( pair );
return( this );
}
VTarget
VTarget::new_to_descriptor( int descriptor )
{
VipsTarget *output;
if( !(output = vips_target_new_to_descriptor( descriptor )) )
throw VError();
VTarget out( output );
return( out );
}
VTarget
VTarget::new_to_file( const char *filename )
{
VipsTarget *output;
if( !(output = vips_target_new_to_file( filename )) )
throw VError();
VTarget out( output );
return( out );
}
VTarget
VTarget::new_to_memory()
{
VipsTarget *output;
if( !(output = vips_target_new_to_memory()) )
throw VError();
VTarget out( output );
return( out );
}
VOption *
VOption::set( const char *name, const VTarget value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_TARGET );
g_value_set_object( &pair->value, value.get_target() );
options.push_back( pair );
return( this );
}
VIPS_NAMESPACE_END

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,7 @@ VInterpolate::new_from_name( const char *name, VOption *options )
}
VOption *
VOption::set( const char *name, VInterpolate value )
VOption::set( const char *name, const VInterpolate value )
{
Pair *pair = new Pair( name );

View File

@ -25,7 +25,7 @@
import argparse
from pyvips import Operation, GValue, Error, \
from pyvips import Introspect, Operation, GValue, Error, \
ffi, gobject_lib, type_map, type_from_name, nickname_find, type_name
# turn a GType into a C++ type
@ -37,12 +37,17 @@ gtype_to_cpp = {
GValue.refstr_type: 'char *',
GValue.gflags_type: 'int',
GValue.image_type: 'VImage',
GValue.source_type: 'VSource',
GValue.target_type: 'VTarget',
GValue.array_int_type: 'std::vector<int>',
GValue.array_double_type: 'std::vector<double>',
GValue.array_image_type: 'std::vector<VImage>',
GValue.blob_type: 'VipsBlob *'
}
cplusplus_suffixes = ('*', '&')
cplusplus_keywords = ('case', 'switch')
# values for VipsArgumentFlags
_REQUIRED = 1
_INPUT = 16
@ -78,67 +83,43 @@ def cppize(name):
def generate_operation(operation_name, declaration_only=False):
op = Operation.new_from_name(operation_name)
intro = Introspect.get(operation_name)
# we are only interested in non-deprecated args
args = [[name, flags] for name, flags in op.get_args()
if not flags & _DEPRECATED]
# find the first required input image arg, if any ... that will be self
member_x = None
for name, flags in args:
if ((flags & _INPUT) != 0 and
(flags & _REQUIRED) != 0 and
op.get_typeof(name) == GValue.image_type):
member_x = name
break
required_input = [name for name, flags in args
if (flags & _INPUT) != 0 and
(flags & _REQUIRED) != 0 and
name != member_x]
required_output = [name for name, flags in args
if ((flags & _OUTPUT) != 0 and
(flags & _REQUIRED) != 0) or
((flags & _INPUT) != 0 and
(flags & _REQUIRED) != 0 and
(flags & _MODIFY) != 0) and
name != member_x]
required_output = [name for name in intro.required_output if name != intro.member_x]
has_output = len(required_output) >= 1
# Add a C++ style comment block with some additional markings (@param,
# Add a C++ style comment block with some additional markings (@param,
# @return)
if declaration_only:
result = '\n/**\n * {}.'.format(op.get_description().capitalize())
result = '\n/**\n * {}.'.format(intro.description.capitalize())
for name in required_input:
for name in intro.method_args:
result += '\n * @param {} {}.' \
.format(cppize(name), op.get_blurb(name))
.format(cppize(name), intro.details[name]['blurb'])
if has_output:
# skip the first element
for name in required_output[1:]:
result += '\n * @param {} {}.' \
.format(cppize(name), op.get_blurb(name))
.format(cppize(name), intro.details[name]['blurb'])
result += '\n * @param options Optional options.'
if has_output:
result += '\n * @return {}.' \
.format(op.get_blurb(required_output[0]))
.format(intro.details[required_output[0]]['blurb'])
result += '\n */\n'
else:
result = '\n'
if member_x is None and declaration_only:
if intro.member_x is None and declaration_only:
result += 'static '
if has_output:
# the first output arg will be used as the result
cpp_type = get_cpp_type(op.get_typeof(required_output[0]))
spacing = '' if cpp_type.endswith('*') else ' '
cpp_type = get_cpp_type(intro.details[required_output[0]]['type'])
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}'.format(cpp_type, spacing)
else:
result += 'void '
@ -146,26 +127,32 @@ def generate_operation(operation_name, declaration_only=False):
if not declaration_only:
result += 'VImage::'
result += '{0}( '.format(operation_name)
for name in required_input:
gtype = op.get_typeof(name)
cplusplus_operation = operation_name
if operation_name in cplusplus_keywords:
cplusplus_operation += '_image'
result += '{0}( '.format(cplusplus_operation)
for name in intro.method_args:
details = intro.details[name]
gtype = details['type']
cpp_type = get_cpp_type(gtype)
spacing = '' if cpp_type.endswith('*') else ' '
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}{2}, '.format(cpp_type, spacing, cppize(name))
# output params are passed by reference
if has_output:
# skip the first element
for name in required_output[1:]:
gtype = op.get_typeof(name)
details = intro.details[name]
gtype = details['type']
cpp_type = get_cpp_type(gtype)
spacing = '' if cpp_type.endswith('*') else ' '
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}*{2}, '.format(cpp_type, spacing, cppize(name))
result += 'VOption *options {0})'.format('= 0 ' if declaration_only else '')
# if no 'this' available, it's a class method and they are all const
if member_x is not None:
if intro.member_x is not None:
result += ' const'
if declaration_only:
@ -178,17 +165,17 @@ def generate_operation(operation_name, declaration_only=False):
if has_output:
# the first output arg will be used as the result
name = required_output[0]
cpp_type = get_cpp_type(op.get_typeof(name))
spacing = '' if cpp_type.endswith('*') else ' '
cpp_type = get_cpp_type(intro.details[name]['type'])
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += ' {0}{1}{2};\n\n'.format(cpp_type, spacing, cppize(name))
result += ' call( "{0}",\n'.format(operation_name)
result += ' (options ? options : VImage::option())'
if member_x is not None:
if intro.member_x is not None:
result += '->\n'
result += ' set( "{0}", *this )'.format(member_x)
result += ' set( "{0}", *this )'.format(intro.member_x)
all_required = required_input
all_required = intro.method_args
if has_output:
# first element needs to be passed by reference
@ -223,10 +210,10 @@ def generate_operators(declarations_only=False):
nickname = nickname_find(gtype)
try:
# can fail for abstract types
op = Operation.new_from_name(nickname)
intro = Introspect.get(nickname)
# we are only interested in non-deprecated operations
if (op.get_flags() & _OPERATION_DEPRECATED) == 0:
if (intro.flags & _OPERATION_DEPRECATED) == 0:
all_nicknames.append(nickname)
except Error:
pass

View File

@ -2,6 +2,7 @@ pkginclude_HEADERS = \
VError8.h \
VImage8.h \
VInterpolate8.h \
VConnection8.h \
vips8 \
vips-operators.h

View File

@ -0,0 +1,96 @@
// VIPS connection wrapper
/*
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 VIPS_VCONNECTION_H
#define VIPS_VCONNECTION_H
#include <vips/vips.h>
VIPS_NAMESPACE_START
class VSource : VObject
{
public:
VSource( VipsSource *input, VSteal steal = STEAL ) :
VObject( (VipsObject *) input, steal )
{
}
static
VSource new_from_descriptor( int descriptor );
static
VSource new_from_file( const char *filename );
static
VSource new_from_blob( VipsBlob *blob );
static
VSource new_from_memory( const void *data,
size_t size );
static
VSource new_from_options( const char *options );
VipsSource *
get_source() const
{
return( (VipsSource *) VObject::get_object() );
}
};
class VTarget : VObject
{
public:
VTarget( VipsTarget *output, VSteal steal = STEAL ) :
VObject( (VipsObject *) output, steal )
{
}
static
VTarget new_to_descriptor( int descriptor );
static
VTarget new_to_file( const char *filename );
static
VTarget new_to_memory();
VipsTarget *
get_target() const
{
return( (VipsTarget *) VObject::get_object() );
}
};
VIPS_NAMESPACE_END
#endif /*VIPS_VCONNECTION_H*/

View File

@ -81,7 +81,7 @@ public:
}
#endif /*VIPS_DEBUG_VERBOSE*/
if( !steal ) {
if( !steal && vobject ) {
#ifdef VIPS_DEBUG_VERBOSE
printf( " reffing object\n" );
#endif /*VIPS_DEBUG_VERBOSE*/
@ -98,22 +98,21 @@ public:
VObject( const VObject &a ) :
vobject( a.vobject )
{
g_assert( VIPS_IS_OBJECT( a.vobject ) );
g_assert( !vobject ||
VIPS_IS_OBJECT( vobject ) );
#ifdef VIPS_DEBUG_VERBOSE
printf( "VObject copy constructor, obj = %p\n",
vobject );
printf( " reffing object\n" );
#endif /*VIPS_DEBUG_VERBOSE*/
g_object_ref( vobject );
if( vobject )
g_object_ref( vobject );
}
// assignment ... we must delete the old ref
// old can be NULL, new must not be NULL
VObject &operator=( const VObject &a )
{
VipsObject *old_vobject;
#ifdef VIPS_DEBUG_VERBOSE
printf( "VObject assignment\n" );
printf( " reffing %p\n", a.vobject );
@ -122,16 +121,16 @@ public:
g_assert( !vobject ||
VIPS_IS_OBJECT( vobject ) );
g_assert( a.vobject &&
g_assert( !a.vobject ||
VIPS_IS_OBJECT( a.vobject ) );
// delete the old ref at the end ... otherwise "a = a;" could
// unref before reffing again
old_vobject = vobject;
if( a.vobject )
g_object_ref( a.vobject );
if( vobject )
g_object_unref( vobject );
vobject = a.vobject;
g_object_ref( vobject );
if( old_vobject )
g_object_unref( old_vobject );
return( *this );
}
@ -169,6 +168,8 @@ public:
class VIPS_CPLUSPLUS_API VImage;
class VIPS_CPLUSPLUS_API VInterpolate;
class VIPS_CPLUSPLUS_API VSource;
class VIPS_CPLUSPLUS_API VTarget;
class VIPS_CPLUSPLUS_API VOption;
class VOption
@ -220,8 +221,10 @@ public:
VOption *set( const char *name, int value );
VOption *set( const char *name, double value );
VOption *set( const char *name, const char *value );
VOption *set( const char *name, VImage value );
VOption *set( const char *name, VInterpolate value );
VOption *set( const char *name, const VImage value );
VOption *set( const char *name, const VInterpolate value );
VOption *set( const char *name, const VSource value );
VOption *set( const char *name, const VTarget value );
VOption *set( const char *name, std::vector<VImage> value );
VOption *set( const char *name, std::vector<double> value );
VOption *set( const char *name, std::vector<int> value );
@ -510,6 +513,9 @@ public:
static VImage new_from_buffer( const std::string &buf,
const char *option_string, VOption *options = 0 );
static VImage new_from_source( VSource source,
const char *option_string, VOption *options = 0 );
static VImage new_matrix( int width, int height );
static VImage
@ -562,6 +568,9 @@ public:
void write_to_buffer( const char *suffix, void **buf, size_t *size,
VOption *options = 0 ) const;
void write_to_target( const char *suffix, VTarget target,
VOption *options = 0 ) const;
void *
write_to_memory( size_t *size ) const
{

View File

@ -30,12 +30,6 @@
#ifndef VIPS_VINTERPOLATE_H
#define VIPS_VINTERPOLATE_H
#include <list>
#include <complex>
#include <vector>
#include <cstring>
#include <vips/vips.h>
VIPS_NAMESPACE_START
@ -61,4 +55,4 @@ public:
VIPS_NAMESPACE_END
#endif /*VIPS_VIMAGE_H*/
#endif /*VIPS_VINTERPOLATE_H*/

View File

@ -1,5 +1,5 @@
// headers for vips operations
// Wed Apr 24 15:50:21 CEST 2019
// Thu 18 Jun 2020 01:19:31 PM CEST
// this file is generated automatically, do not edit!
/**
@ -296,6 +296,14 @@ VImage cache( VOption *options = 0 ) const;
*/
VImage canny( VOption *options = 0 ) const;
/**
* Use pixel values to pick cases from an array of images.
* @param cases Array of case images.
* @param options Optional options.
* @return Output image.
*/
VImage case_image( std::vector<VImage> cases, VOption *options = 0 ) const;
/**
* Cast an image.
* @param format Format to cast to.
@ -446,7 +454,7 @@ double countlines( VipsDirection direction, VOption *options = 0 ) const;
VImage crop( int left, int top, int width, int height, VOption *options = 0 ) const;
/**
* Load csv from file.
* Load csv.
* @param filename Filename to load from.
* @param options Optional options.
* @return Output image.
@ -454,12 +462,27 @@ VImage crop( int left, int top, int width, int height, VOption *options = 0 ) co
static VImage csvload( const char *filename, VOption *options = 0 );
/**
* Save image to csv file.
* Load csv.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage csvload_source( VSource source, VOption *options = 0 );
/**
* Save image to csv.
* @param filename Filename to save to.
* @param options Optional options.
*/
void csvsave( const char *filename, VOption *options = 0 ) const;
/**
* Save image to csv.
* @param target Target to save to.
* @param options Optional options.
*/
void csvsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Calculate de00.
* @param right Right-hand input image.
@ -774,6 +797,14 @@ static VImage gifload( const char *filename, VOption *options = 0 );
*/
static VImage gifload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load gif with giflib.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage gifload_source( VSource source, VOption *options = 0 );
/**
* Global balance an image mosaic.
* @param options Optional options.
@ -826,6 +857,14 @@ static VImage heifload( const char *filename, VOption *options = 0 );
*/
static VImage heifload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load a heif image.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage heifload_source( VSource source, VOption *options = 0 );
/**
* Save image in heif format.
* @param filename Filename to load from.
@ -840,6 +879,13 @@ void heifsave( const char *filename, VOption *options = 0 ) const;
*/
VipsBlob *heifsave_buffer( VOption *options = 0 ) const;
/**
* Save image in heif format.
* @param target Target to save to.
* @param options Optional options.
*/
void heifsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Form cumulative histogram.
* @param options Optional options.
@ -1029,6 +1075,14 @@ static VImage jpegload( const char *filename, VOption *options = 0 );
*/
static VImage jpegload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load image from jpeg source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage jpegload_source( VSource source, VOption *options = 0 );
/**
* Save image to jpeg file.
* @param filename Filename to save to.
@ -1049,6 +1103,13 @@ VipsBlob *jpegsave_buffer( VOption *options = 0 ) const;
*/
void jpegsave_mime( VOption *options = 0 ) const;
/**
* Save image to jpeg target.
* @param target Target to save to.
* @param options Optional options.
*/
void jpegsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Label regions in an image.
* @param options Optional options.
@ -1112,7 +1173,7 @@ void magicksave( const char *filename, VOption *options = 0 ) const;
VipsBlob *magicksave_buffer( VOption *options = 0 ) const;
/**
* Resample with an mapim image.
* Resample with a map image.
* @param index Index pixels with this.
* @param options Optional options.
* @return Output image.
@ -1296,13 +1357,28 @@ VImage math2_const( VipsOperationMath2 math2, std::vector<double> c, VOption *op
static VImage matload( const char *filename, VOption *options = 0 );
/**
* Load matrix from file.
* Invert an matrix.
* @param options Optional options.
* @return Output image.
*/
VImage matrixinvert( VOption *options = 0 ) const;
/**
* Load matrix.
* @param filename Filename to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage matrixload( const char *filename, VOption *options = 0 );
/**
* Load matrix.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage matrixload_source( VSource source, VOption *options = 0 );
/**
* Print matrix.
* @param options Optional options.
@ -1310,12 +1386,19 @@ static VImage matrixload( const char *filename, VOption *options = 0 );
void matrixprint( VOption *options = 0 ) const;
/**
* Save image to matrix file.
* Save image to matrix.
* @param filename Filename to save to.
* @param options Optional options.
*/
void matrixsave( const char *filename, VOption *options = 0 ) const;
/**
* Save image to matrix.
* @param target Target to save to.
* @param options Optional options.
*/
void matrixsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Find image maximum.
* @param options Optional options.
@ -1436,7 +1519,7 @@ static VImage openexrload( const char *filename, VOption *options = 0 );
static VImage openslideload( const char *filename, VOption *options = 0 );
/**
* Load pdf with libpoppler.
* Load pdf from file.
* @param filename Filename to load from.
* @param options Optional options.
* @return Output image.
@ -1444,13 +1527,21 @@ static VImage openslideload( const char *filename, VOption *options = 0 );
static VImage pdfload( const char *filename, VOption *options = 0 );
/**
* Load pdf with libpoppler.
* Load pdf from buffer.
* @param buffer Buffer to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage pdfload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load pdf from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage pdfload_source( VSource source, VOption *options = 0 );
/**
* Find threshold for percent of pixels.
* @param percent Percent of pixels.
@ -1492,6 +1583,14 @@ static VImage pngload( const char *filename, VOption *options = 0 );
*/
static VImage pngload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load png from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage pngload_source( VSource source, VOption *options = 0 );
/**
* Save image to png file.
* @param filename Filename to save to.
@ -1506,6 +1605,13 @@ void pngsave( const char *filename, VOption *options = 0 ) const;
*/
VipsBlob *pngsave_buffer( VOption *options = 0 ) const;
/**
* Save image to target as png.
* @param target Target to save to.
* @param options Optional options.
*/
void pngsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Load ppm from file.
* @param filename Filename to load from.
@ -1575,6 +1681,22 @@ VImage rad2float( VOption *options = 0 ) const;
*/
static VImage radload( const char *filename, VOption *options = 0 );
/**
* Load rad from buffer.
* @param buffer Buffer to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage radload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load rad from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage radload_source( VSource source, VOption *options = 0 );
/**
* Save image to radiance file.
* @param filename Filename to save to.
@ -1589,6 +1711,13 @@ void radsave( const char *filename, VOption *options = 0 ) const;
*/
VipsBlob *radsave_buffer( VOption *options = 0 ) const;
/**
* Save image to radiance target.
* @param target Target to save to.
* @param options Optional options.
*/
void radsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Rank filter.
* @param width Window width in pixels.
@ -1931,6 +2060,22 @@ static VImage svgload( const char *filename, VOption *options = 0 );
*/
static VImage svgload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load svg from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage svgload_source( VSource source, VOption *options = 0 );
/**
* Find the index of the first non-zero pixel in tests.
* @param tests Table of images to test.
* @param options Optional options.
* @return Output image.
*/
static VImage switch_image( std::vector<VImage> tests, VOption *options = 0 );
/**
* Run an external command.
* @param cmd_format Command to run.
@ -1972,6 +2117,15 @@ static VImage thumbnail_buffer( VipsBlob *buffer, int width, VOption *options =
*/
VImage thumbnail_image( int width, VOption *options = 0 ) const;
/**
* Generate thumbnail from source.
* @param source Source to load from.
* @param width Size to this width.
* @param options Optional options.
* @return Output image.
*/
static VImage thumbnail_source( VSource source, int width, VOption *options = 0 );
/**
* Load tiff from file.
* @param filename Filename to load from.
@ -1988,6 +2142,14 @@ static VImage tiffload( const char *filename, VOption *options = 0 );
*/
static VImage tiffload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load tiff from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage tiffload_source( VSource source, VOption *options = 0 );
/**
* Save image to tiff file.
* @param filename Filename to save to.
@ -2061,6 +2223,14 @@ static VImage webpload( const char *filename, VOption *options = 0 );
*/
static VImage webpload_buffer( VipsBlob *buffer, VOption *options = 0 );
/**
* Load webp from source.
* @param source Source to load from.
* @param options Optional options.
* @return Output image.
*/
static VImage webpload_source( VSource source, VOption *options = 0 );
/**
* Save image to webp file.
* @param filename Filename to save to.
@ -2075,6 +2245,13 @@ void webpsave( const char *filename, VOption *options = 0 ) const;
*/
VipsBlob *webpsave_buffer( VOption *options = 0 ) const;
/**
* Save image to webp target.
* @param target Target to save to.
* @param options Optional options.
*/
void webpsave_target( VTarget target, VOption *options = 0 ) const;
/**
* Make a worley noise image.
* @param width Image width in pixels.

View File

@ -52,5 +52,6 @@
#include "VError8.h"
#include "VImage8.h"
#include "VInterpolate8.h"
#include "VConnection8.h"
#endif /*VIPS_CPLUSPLUS*/

View File

@ -1,5 +1,5 @@
// bodies for vips operations
// Wed Apr 24 15:50:21 CEST 2019
// Thu 18 Jun 2020 01:19:31 PM CEST
// this file is generated automatically, do not edit!
VImage VImage::CMC2LCh( VOption *options ) const
@ -491,6 +491,19 @@ VImage VImage::canny( VOption *options ) const
return( out );
}
VImage VImage::case_image( std::vector<VImage> cases, VOption *options ) const
{
VImage out;
call( "case",
(options ? options : VImage::option())->
set( "index", *this )->
set( "out", &out )->
set( "cases", cases ) );
return( out );
}
VImage VImage::cast( VipsBandFormat format, VOption *options ) const
{
VImage out;
@ -741,6 +754,18 @@ VImage VImage::csvload( const char *filename, VOption *options )
return( out );
}
VImage VImage::csvload_source( VSource source, VOption *options )
{
VImage out;
call( "csvload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::csvsave( const char *filename, VOption *options ) const
{
call( "csvsave",
@ -749,6 +774,14 @@ void VImage::csvsave( const char *filename, VOption *options ) const
set( "filename", filename ) );
}
void VImage::csvsave_target( VTarget target, VOption *options ) const
{
call( "csvsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::dE00( VImage right, VOption *options ) const
{
VImage out;
@ -1205,6 +1238,18 @@ VImage VImage::gifload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::gifload_source( VSource source, VOption *options )
{
VImage out;
call( "gifload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
VImage VImage::globalbalance( VOption *options ) const
{
VImage out;
@ -1284,6 +1329,18 @@ VImage VImage::heifload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::heifload_source( VSource source, VOption *options )
{
VImage out;
call( "heifload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::heifsave( const char *filename, VOption *options ) const
{
call( "heifsave",
@ -1304,6 +1361,14 @@ VipsBlob *VImage::heifsave_buffer( VOption *options ) const
return( buffer );
}
void VImage::heifsave_target( VTarget target, VOption *options ) const
{
call( "heifsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::hist_cum( VOption *options ) const
{
VImage out;
@ -1615,6 +1680,18 @@ VImage VImage::jpegload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::jpegload_source( VSource source, VOption *options )
{
VImage out;
call( "jpegload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::jpegsave( const char *filename, VOption *options ) const
{
call( "jpegsave",
@ -1642,6 +1719,14 @@ void VImage::jpegsave_mime( VOption *options ) const
set( "in", *this ) );
}
void VImage::jpegsave_target( VTarget target, VOption *options ) const
{
call( "jpegsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::labelregions( VOption *options ) const
{
VImage mask;
@ -1995,6 +2080,18 @@ VImage VImage::matload( const char *filename, VOption *options )
return( out );
}
VImage VImage::matrixinvert( VOption *options ) const
{
VImage out;
call( "matrixinvert",
(options ? options : VImage::option())->
set( "in", *this )->
set( "out", &out ) );
return( out );
}
VImage VImage::matrixload( const char *filename, VOption *options )
{
VImage out;
@ -2007,6 +2104,18 @@ VImage VImage::matrixload( const char *filename, VOption *options )
return( out );
}
VImage VImage::matrixload_source( VSource source, VOption *options )
{
VImage out;
call( "matrixload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::matrixprint( VOption *options ) const
{
call( "matrixprint",
@ -2022,6 +2131,14 @@ void VImage::matrixsave( const char *filename, VOption *options ) const
set( "filename", filename ) );
}
void VImage::matrixsave_target( VTarget target, VOption *options ) const
{
call( "matrixsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
double VImage::max( VOption *options ) const
{
double out;
@ -2223,6 +2340,18 @@ VImage VImage::pdfload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::pdfload_source( VSource source, VOption *options )
{
VImage out;
call( "pdfload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
int VImage::percent( double percent, VOption *options ) const
{
int threshold;
@ -2286,6 +2415,18 @@ VImage VImage::pngload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::pngload_source( VSource source, VOption *options )
{
VImage out;
call( "pngload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::pngsave( const char *filename, VOption *options ) const
{
call( "pngsave",
@ -2306,6 +2447,14 @@ VipsBlob *VImage::pngsave_buffer( VOption *options ) const
return( buffer );
}
void VImage::pngsave_target( VTarget target, VOption *options ) const
{
call( "pngsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::ppmload( const char *filename, VOption *options )
{
VImage out;
@ -2413,6 +2562,30 @@ VImage VImage::radload( const char *filename, VOption *options )
return( out );
}
VImage VImage::radload_buffer( VipsBlob *buffer, VOption *options )
{
VImage out;
call( "radload_buffer",
(options ? options : VImage::option())->
set( "out", &out )->
set( "buffer", buffer ) );
return( out );
}
VImage VImage::radload_source( VSource source, VOption *options )
{
VImage out;
call( "radload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::radsave( const char *filename, VOption *options ) const
{
call( "radsave",
@ -2433,6 +2606,14 @@ VipsBlob *VImage::radsave_buffer( VOption *options ) const
return( buffer );
}
void VImage::radsave_target( VTarget target, VOption *options ) const
{
call( "radsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::rank( int width, int height, int index, VOption *options ) const
{
VImage out;
@ -2977,6 +3158,30 @@ VImage VImage::svgload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::svgload_source( VSource source, VOption *options )
{
VImage out;
call( "svgload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
VImage VImage::switch_image( std::vector<VImage> tests, VOption *options )
{
VImage out;
call( "switch",
(options ? options : VImage::option())->
set( "out", &out )->
set( "tests", tests ) );
return( out );
}
void VImage::system( const char *cmd_format, VOption *options )
{
call( "system",
@ -3035,6 +3240,19 @@ VImage VImage::thumbnail_image( int width, VOption *options ) const
return( out );
}
VImage VImage::thumbnail_source( VSource source, int width, VOption *options )
{
VImage out;
call( "thumbnail_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source )->
set( "width", width ) );
return( out );
}
VImage VImage::tiffload( const char *filename, VOption *options )
{
VImage out;
@ -3059,6 +3277,18 @@ VImage VImage::tiffload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::tiffload_source( VSource source, VOption *options )
{
VImage out;
call( "tiffload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::tiffsave( const char *filename, VOption *options ) const
{
call( "tiffsave",
@ -3170,6 +3400,18 @@ VImage VImage::webpload_buffer( VipsBlob *buffer, VOption *options )
return( out );
}
VImage VImage::webpload_source( VSource source, VOption *options )
{
VImage out;
call( "webpload_source",
(options ? options : VImage::option())->
set( "out", &out )->
set( "source", source ) );
return( out );
}
void VImage::webpsave( const char *filename, VOption *options ) const
{
call( "webpsave",
@ -3190,6 +3432,14 @@ VipsBlob *VImage::webpsave_buffer( VOption *options ) const
return( buffer );
}
void VImage::webpsave_target( VTarget target, VOption *options ) const
{
call( "webpsave_target",
(options ? options : VImage::option())->
set( "in", *this )->
set( "target", target ) );
}
VImage VImage::worley( int width, int height, VOption *options )
{
VImage out;

View File

@ -1,13 +1,13 @@
<refmeta>
<refentrytitle>Opening files</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refmeta>
<refentrytitle>Opening files</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Opening</refname>
<refpurpose>How libvips opens files</refpurpose>
</refnamediv>
<refnamediv>
<refname>Opening</refname>
<refpurpose>How libvips opens files</refpurpose>
</refnamediv>
libvips now has at least four different ways of opening image files, each
best for different file types, file sizes and image use cases. libvips tries

View File

@ -16,7 +16,7 @@
<para>
This page tries to explain what the different strategies are and when each is used. If you are running into unexpected memory, disc or CPU use, this might be helpful. <literal>vips_image_new_from_file()</literal> has the official documentation.
</para>
<refsect3 id="direct-access">
<section xml:id="direct-access">
<title>Direct access</title>
<para>
This is the fastest and simplest one. The file is mapped directly into the processs address space and can be read with ordinary pointer access. Small files are completely mapped; large files are mapped in a series of small windows that are shared and which scroll about as pixels are read. Files which are accessed like this can be read by many threads at once, making them especially quick. They also interact well with the computers operating system: your OS will use spare memory to cache recently used chunks of the file.
@ -25,10 +25,10 @@
For this to be possible, the file format needs to be a simple dump of a memory array. libvips supports direct access for vips, 8-bit binary ppm/pbm/pnm, analyse and raw.
</para>
<para>
libvips has a special direct write mode where pixels can be written directly to the file image. This is used for the <ulink url="libvips-draw.html">draw operators</ulink>.
libvips has a special direct write mode where pixels can be written directly to the file image. This is used for the <link xlink:href="libvips-draw.html">draw operators</link>.
</para>
</refsect3>
<refsect3 id="random-access-via-load-library">
</section>
<section xml:id="random-access-via-load-library">
<title>Random access via load library</title>
<para>
Some image file formats have libraries which allow true random access to image pixels. For example, libtiff lets you read any tile out of a tiled tiff image very quickly. Because the libraries allow true random access, libvips can simply hook the image load library up to the input of the operation pipeline.
@ -39,8 +39,8 @@
<para>
libvips can load tiled tiff, tiled OpenEXR, FITS and OpenSlide images in this manner.
</para>
</refsect3>
<refsect3 id="full-decompression">
</section>
<section xml:id="full-decompression">
<title>Full decompression</title>
<para>
Many image load libraries do not support random access. In order to use images of this type as inputs to pipelines, libvips has to convert them to a random access format first.
@ -54,8 +54,8 @@
<para>
This is the slowest and most memory-hungry way to read files, but its unavoidable for many file formats. Unless you can use the next one!
</para>
</refsect3>
<refsect3 id="sequential-access">
</section>
<section xml:id="sequential-access">
<title>Sequential access</title>
<para>
This a fairly recent addition to libvips and is a hybrid of the previous two.
@ -90,7 +90,7 @@ $ vips shrink fred.png jim.png 10 10
<para>
This is done automatically in command-line operation. In programs, you need to set <literal>access</literal> to #VIPS_ACCESS_SEQUENTIAL in calls to functions like vips_image_new_from_file().
</para>
</refsect3>
</section>
</refentry>

View File

@ -1,13 +1,13 @@
<refmeta>
<refentrytitle>Using `vipsthumbnail`</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refmeta>
<refentrytitle>Using `vipsthumbnail`</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refnamediv>
<refname>`vipsthumbnail`</refname>
<refpurpose>Introduction to `vipsthumbnail`, with examples</refpurpose>
</refnamediv>
<refnamediv>
<refname>`vipsthumbnail`</refname>
<refpurpose>Introduction to `vipsthumbnail`, with examples</refpurpose>
</refnamediv>
libvips ships with a handy command-line image thumbnailer, `vipsthumbnail`.
This page introduces it, with some examples.
@ -267,15 +267,19 @@ $ ls -l tn_shark.jpg
-rw-rr 1 john john 7295 Nov  9 14:33 tn_shark.jpg
```
Now encode with sRGB and delete any embedded profile:
Now transform to sRGB and don't attach a profile (you can also use `strip`,
though that will remove *all* metadata from the image):
```
$ vipsthumbnail shark.jpg --eprofile /usr/share/color/icc/sRGB.icc --delete
$ vipsthumbnail shark.jpg --eprofile srgb -o tn_shark.jpg[profile=none]
$ ls -l tn_shark.jpg
-rw-rr 1 john john 4229 Nov  9 14:33 tn_shark.jpg
```
Itll look identical to a user, but be almost half the size.
(You can use the filename of any RGB profile. The magic string `srgb` selects a
high-quality sRGB profile that's built into libvips.)
`tn_shark.jpg` will look identical to a user, but it's almost half the size.
You can also specify a fallback input profile to use if the image has no
embedded one. This can often happen with CMYK images, producing an error
@ -291,23 +295,11 @@ If you supply a CMYK profile, it will be able to convert the image,
for example:
```
$ vipsthumbnail kgdev.jpg --iprofile /usr/share/color/icc/colord/FOGRA28L_webcoated.icc
$ vipsthumbnail kgdev.jpg --iprofile cmyk
```
I've had good results with this profile:
https://github.com/libvips/nip2/blob/master/share/nip2/data/cmyk.icm
It makes nice-looking images from most CMYK files, and is completely free.
# Auto-rotate
Many JPEG files have a hint set in the header giving the image orientation. If
you strip out the metadata, this hint will be lost, and the image will appear
to be rotated.
If you use the `--rotate` option, `vipsthumbnail` examines the image header and
if there's an orientation tag, applies and removes it.
(As before, the magic string `cmyk` selects a high-quality CMYK profile that's
built into libvips, but you can use any CMYK profile you like.)
# Final suggestion
@ -316,7 +308,7 @@ Putting all this together, I suggest this as a sensible set of options:
```
$ vipsthumbnail fred.jpg \
--size 128 \
--eprofile srgb \
-o tn_%s.jpg[optimize_coding,strip] \
--eprofile /usr/share/color/icc/sRGB.icc \
--rotate
--eprofile srgb
```

View File

@ -21,7 +21,7 @@ $filename = &quot;image.jpg&quot;;
$image = Vips\Image::thumbnail($filename, 200, [&quot;height&quot; =&gt; 200]);
$image-&gt;writeToFile(&quot;my-thumbnail.jpg&quot;);
</programlisting>
<refsect3 id="libvips-options">
<section xml:id="libvips-options">
<title>libvips options</title>
<para>
<literal>vipsthumbnail</literal> supports the usual range of vips command-line options. A few of them are useful:
@ -38,8 +38,8 @@ $image-&gt;writeToFile(&quot;my-thumbnail.jpg&quot;);
<para>
<literal>--vips-info</literal> shows a higher level view of the operations that <literal>vipsthumbnail</literal> is running. 
</para>
</refsect3>
<refsect3 id="looping">
</section>
<section xml:id="looping">
<title>Looping</title>
<para>
<literal>vipsthumbnail</literal> can process many images in one command. For example:
@ -56,8 +56,8 @@ $ vipsthumbnail *.jpg
<programlisting>
$ parallel vipsthumbnail ::: *.jpg
</programlisting>
</refsect3>
<refsect3 id="thumbnail-size">
</section>
<section xml:id="thumbnail-size">
<title>Thumbnail size</title>
<para>
You can set the bounding box of the generated thumbnail with the <literal>--size</literal> option. For example:
@ -80,8 +80,8 @@ $ vipsthumbnail shark.jpg --size 200x
<para>
You can append <literal>!</literal> to force a resize to the exact target size, breaking the aspect ratio.
</para>
</refsect3>
<refsect3 id="cropping">
</section>
<section xml:id="cropping">
<title>Cropping</title>
<para>
<literal>vipsthumbnail</literal> normally shrinks images to fit within the box set by <literal>--size</literal>. You can use the <literal>--smartcrop</literal> option to crop to fill the box instead. Excess pixels are trimmed away using the strategy you set. For example:
@ -92,30 +92,28 @@ $ vipsthumbnail owl.jpg --smartcrop attention -s 128
<para>
Where <literal>owl.jpg</literal> is an off-centre composition:
</para>
<figure>
<mediaobject>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="owl.jpg" />
</imageobject>
<textobject><phrase></phrase></textobject>
</mediaobject>
</figure>
</inlinemediaobject>
</para>
<para>
Gives this result:
</para>
<figure>
<mediaobject>
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="tn_owl.jpg" />
</imageobject>
<textobject><phrase></phrase></textobject>
</mediaobject>
</figure>
</inlinemediaobject>
</para>
<para>
First it shrinks the image to get the vertical axis to 128 pixels, then crops down to 128 pixels across using the <literal>attention</literal> strategy. This one searches the image for features which might catch a human eye, see <literal>vips_smartcrop()</literal> for details.
</para>
</refsect3>
<refsect3 id="linear-light">
</section>
<section xml:id="linear-light">
<title>Linear light</title>
<para>
Shrinking images involves combining many pixels into one. Arithmetic averaging really ought to be in terms of the number of photons, but (for historical reasons) the values stored in image files are usually related to the voltage that should be applied to the electron gun in a CRT display.
@ -142,8 +140,8 @@ real 0m4.660s
user 0m4.640s
sys 0m0.016s
</programlisting>
</refsect3>
<refsect3 id="output-directory">
</section>
<section xml:id="output-directory">
<title>Output directory</title>
<para>
You set the thumbnail write parameters with the <literal>-o</literal> option. This is a pattern which the input filename is pasted into to produce the output filename. For example:
@ -172,8 +170,8 @@ $ vipsthumbnail fred.jpg ../jim.tif -o mythumbs/tn_%s.jpg
<para>
Now both input files will have thumbnails written to a subdirectory of their current directory.
</para>
</refsect3>
<refsect3 id="output-format-and-options">
</section>
<section xml:id="output-format-and-options">
<title>Output format and options</title>
<para>
You can use <literal>-o</literal> to specify the thumbnail image format too. For example: 
@ -247,8 +245,8 @@ $ vipsthumbnail 42-32157534.jpg -o x.jpg[optimize_coding,strip]
$ ls -l x.jpg
-rw-rr 1 john john 3600 Nov 12 21:27 x.jpg
</programlisting>
</refsect3>
<refsect3 id="colour-management">
</section>
<section xml:id="colour-management">
<title>Colour management</title>
<para>
<literal>vipsthumbnail</literal> will optionally put images through LittleCMS for you. You can use this to move all thumbnails to the same colour space. All web browsers assume that images without an ICC profile are in sRGB colourspace, so if you move your thumbnails to sRGB, you can strip all the embedded profiles. This can save several kb per thumbnail.
@ -262,15 +260,18 @@ $ ls -l tn_shark.jpg
-rw-rr 1 john john 7295 Nov  9 14:33 tn_shark.jpg
</programlisting>
<para>
Now encode with sRGB and delete any embedded profile:
Now transform to sRGB and dont attach a profile (you can also use <literal>strip</literal>, though that will remove <emphasis>all</emphasis> metadata from the image):
</para>
<programlisting>
$ vipsthumbnail shark.jpg --eprofile /usr/share/color/icc/sRGB.icc --delete
$ vipsthumbnail shark.jpg --eprofile srgb -o tn_shark.jpg[profile=none]
$ ls -l tn_shark.jpg
-rw-rr 1 john john 4229 Nov  9 14:33 tn_shark.jpg
</programlisting>
<para>
Itll look identical to a user, but be almost half the size.
(You can use the filename of any RGB profile. The magic string <literal>srgb</literal> selects a high-quality sRGB profile thats built into libvips.)
</para>
<para>
<literal>tn_shark.jpg</literal> will look identical to a user, but its almost half the size.
</para>
<para>
You can also specify a fallback input profile to use if the image has no embedded one. This can often happen with CMYK images, producing an error message like:
@ -284,28 +285,13 @@ vips_colourspace: no known route from 'cmyk' to 'srgb'
If you supply a CMYK profile, it will be able to convert the image, for example:
</para>
<programlisting>
$ vipsthumbnail kgdev.jpg --iprofile /usr/share/color/icc/colord/FOGRA28L_webcoated.icc
$ vipsthumbnail kgdev.jpg --iprofile cmyk
</programlisting>
<para>
Ive had good results with this profile:
(As before, the magic string <literal>cmyk</literal> selects a high-quality CMYK profile thats built into libvips, but you can use any CMYK profile you like.)
</para>
<para>
https://github.com/libvips/nip2/blob/master/share/nip2/data/cmyk.icm
</para>
<para>
It makes nice-looking images from most CMYK files, and is completely free.
</para>
</refsect3>
<refsect3 id="auto-rotate">
<title>Auto-rotate</title>
<para>
Many JPEG files have a hint set in the header giving the image orientation. If you strip out the metadata, this hint will be lost, and the image will appear to be rotated.
</para>
<para>
If you use the <literal>--rotate</literal> option, <literal>vipsthumbnail</literal> examines the image header and if theres an orientation tag, applies and removes it.
</para>
</refsect3>
<refsect3 id="final-suggestion">
</section>
<section xml:id="final-suggestion">
<title>Final suggestion</title>
<para>
Putting all this together, I suggest this as a sensible set of options:
@ -313,11 +299,11 @@ $ vipsthumbnail kgdev.jpg --iprofile /usr/share/color/icc/colord/FOGRA28L_webcoa
<programlisting>
$ vipsthumbnail fred.jpg \
--size 128 \
--eprofile srgb \
-o tn_%s.jpg[optimize_coding,strip] \
--eprofile /usr/share/color/icc/sRGB.icc \
--rotate
--eprofile srgb
</programlisting>
</refsect3>
</section>
</refentry>

View File

@ -1,13 +1,13 @@
<refmeta>
<refentrytitle>How to write bindings</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refmeta>
<refentrytitle>How to write bindings</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>libvips</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Binding</refname>
<refpurpose>Writing bindings for libvips</refpurpose>
</refnamediv>
<refnamediv>
<refname>Binding</refname>
<refpurpose>Writing bindings for libvips</refpurpose>
</refnamediv>
There are full libvips bindings for quite a few environments now: C, C++,
command-line, Ruby, PHP, Lua, Python and JavaScript (node).
@ -80,7 +80,7 @@ main( int argc, char **argv )
/* Call the operation. This will look up the operation+args in the vips
* operation cache and either return a previous operation, or build
* this one. In either case, we have a new ref we mst release.
* this one. In either case, we have a new ref we must release.
*/
if( !(new_op = vips_cache_operation_build( op )) ) {
g_object_unref( op );
@ -114,7 +114,7 @@ main( int argc, char **argv )
```
libvips has a couple of extra things to let you examine the arguments and
types of an operator at runtime. Use vips_lib.vips_argument_map() to loop
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.
@ -151,7 +151,7 @@ operator overloads, and various other useful features.
# Dynamic language with FFI
Languages like Ruby, Python, JavaScript and Lua can't call C directly, but
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.
@ -216,4 +216,4 @@ $ yelp-build html .
```
To make HTML docs. This is an easy way to see what you can call in the
library.
library.

View File

@ -16,7 +16,7 @@
<para>
This chapter runs through the four main styles that have been found to work well. If you want to write a new binding, one of these should be close to what you need.
</para>
<refsect3 id="dont-bind-the-top-level-c-api">
<section xml:id="dont-bind-the-top-level-c-api">
<title>Dont 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.
@ -79,7 +79,7 @@ main( int argc, char **argv )
/* Call the operation. This will look up the operation+args in the vips
* operation cache and either return a previous operation, or build
* this one. In either case, we have a new ref we mst release.
* this one. In either case, we have a new ref we must release.
*/
if( !(new_op = vips_cache_operation_build( op )) ) {
g_object_unref( op );
@ -112,13 +112,13 @@ main( int argc, char **argv )
}
</programlisting>
<para>
libvips has a couple of extra things to let you examine the arguments and types of an operator at runtime. Use vips_lib.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.
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 id="compiled-language-which-can-call-c">
</section>
<section 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.
@ -144,23 +144,23 @@ VImage VImage::invert( VOption *options )
<para>
The <literal>VImage</literal> class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features.
</para>
</refsect3>
<refsect3 id="dynamic-language-with-ffi">
</section>
<section xml:id="dynamic-language-with-ffi">
<title>Dynamic language with FFI</title>
<para>
Languages like Ruby, Python, JavaScript and Lua cant 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.
Languages like Ruby, Python, JavaScript and LuaJIT cant 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.
</para>
</refsect3>
<refsect3 id="dynamic-langauge-without-ffi">
</section>
<section 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.
</para>
</refsect3>
<refsect3 id="gobject-introspection">
</section>
<section xml:id="gobject-introspection">
<title>gobject-introspection</title>
<para>
The C source code to libvips has been marked up with special comments describing the interface in a standard way. These comments are read by the <literal>gobject-introspection</literal> package when libvips is compiled and used to generate a typelib, a description of how to call the library. Many languages have gobject-introspection packages: all you need to do to call libvips from your favorite language is to start g-o-i, load the libvips typelib, and you should have the whole library available. For example, from Python its as simple as:
@ -177,8 +177,8 @@ from gi.repository import Vips
<para>
If you have a choice, I would recommend simply using FFI.
</para>
</refsect3>
<refsect3 id="documentation">
</section>
<section xml:id="documentation">
<title>Documentation</title>
<para>
You can generate searchable docs from a <code>.gir</code> (the thing that is built from scanning libvips and which in turn turn the typelib is made from) with <command>g-ir-doc-tool</command>, for example:
@ -202,7 +202,7 @@ $ yelp-build html .
<para>
To make HTML docs. This is an easy way to see what you can call in the library.
</para>
</refsect3>
</section>
</refentry>

File diff suppressed because it is too large Load Diff

68
doc/gen-function-list.py Executable file → Normal file
View File

@ -15,21 +15,28 @@
# <entry>vips_gamma()</entry>
# </row>
from pyvips import Operation, Error, \
from pyvips import Introspect, Operation, Error, \
ffi, type_map, type_from_name, nickname_find
# for VipsOperationFlags
_OPERATION_DEPRECATED = 8
def gen_function(operation_name):
op = Operation.new_from_name(operation_name)
def gen_function(operation_name, overloads):
intro = Introspect.get(operation_name)
print('<row>')
print(' <entry>{}</entry>'.format(operation_name))
print(' <entry>{}</entry>'.format(op.get_description().capitalize()))
print(' <entry>vips_{}()</entry>'.format(operation_name))
print('</row>')
c_operations = 'vips_{}()'.format(operation_name)
if overloads:
c_operations += ', ' + (', '.join('vips_{}()'.format(n) for n in overloads))
result = '<row>\n'
result += ' <entry>{}</entry>\n'.format(operation_name)
result += ' <entry>{}</entry>\n'.format(intro.description.capitalize())
result += ' <entry>{}</entry>\n'.format(c_operations)
result += '</row>'
return result
def gen_function_list():
@ -39,10 +46,10 @@ def gen_function_list():
nickname = nickname_find(gtype)
try:
# can fail for abstract types
op = Operation.new_from_name(nickname)
intro = Introspect.get(nickname)
# we are only interested in non-deprecated operations
if (op.get_flags() & _OPERATION_DEPRECATED) == 0:
if (intro.flags & _OPERATION_DEPRECATED) == 0:
all_nicknames.append(nickname)
except Error:
pass
@ -53,15 +60,48 @@ def gen_function_list():
type_map(type_from_name('VipsOperation'), add_nickname)
# add 'missing' synonyms by hand
all_nicknames.append('crop')
# make list unique and sort
all_nicknames = list(set(all_nicknames))
all_nicknames.sort()
# make dict with overloads
overloads = {
'bandbool': ['bandand', 'bandor', 'bandeor', 'bandmean'],
'bandjoin': ['bandjoin2'],
'bandjoin_const': ['bandjoin_const1'],
'boolean': ['andimage', 'orimage', 'eorimage', 'lshift', 'rshift'],
'cast': ['cast_uchar', 'cast_char', 'cast_ushort', 'cast_short' 'cast_uint', 'cast_int', 'cast_float',
'cast_double', 'cast_complex', 'cast_dpcomplex'],
'complex': ['polar', 'rect', 'conj'],
'complex2': ['cross_phase'],
'complexget': ['real', 'imag'],
'draw_circle': ['draw_circle1'],
'draw_flood': ['draw_flood1'],
'draw_line': ['draw_line1'],
'draw_mask': ['draw_mask1'],
'draw_rect': ['draw_rect1', 'draw_point', 'draw_point1'],
'extract_area': ['crop'],
'linear': ['linear1'],
'math': ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'exp', 'exp10', 'log', 'log10'],
'math2': ['pow', 'wop'],
'rank': ['median'],
'relational': ['equal', 'notequal', 'less', 'lesseq', 'more', 'moreeq'],
'remainder_const': ['remainder_const1'],
'round': ['floor', 'ceil', 'rint'],
}
overloads['boolean_const'] = [o + '_const' for o in overloads['boolean']] + ['boolean_const1'] + \
[o + '_const1' for o in overloads['boolean']]
overloads['math2_const'] = [o + '_const' for o in overloads['boolean']] + ['math2_const1'] + \
[o + '_const1' for o in overloads['boolean']]
overloads['relational_const'] = [o + '_const' for o in overloads['relational']] + ['relational_const1'] + \
[o + '_const1' for o in overloads['relational']]
for nickname in all_nicknames:
gen_function(nickname)
result = gen_function(nickname, overloads[nickname] if nickname in overloads else None)
print(result)
if __name__ == '__main__':

View File

@ -61,6 +61,8 @@
<xi:include href="xml/object.xml"/>
<xi:include href="xml/threadpool.xml"/>
<xi:include href="xml/buf.xml"/>
<xi:include href="xml/connection.xml"/>
<xi:include href="xml/sbuf.xml"/>
<xi:include href="xml/basic.xml"/>
</chapter>

View File

@ -25,4 +25,6 @@ libstandaloneengine_a_SOURCES = StandaloneFuzzTargetMain.c
check_PROGRAMS = $(FUZZPROGS)
noinst_LIBRARIES = $(FUZZLIBS)
EXTRA_DIST = $(TESTS)
EXTRA_DIST = \
$(TESTS) \
common_fuzzer_corpus

View File

@ -1,15 +0,0 @@
P2
#vips2ppm - Fri Aug 23 12:48:07 2019
10 10
255
96 101 113 118 124 130 136 141 147 150
81 87 98 101 107 112 117 123 130 135
73 78 85 90 95 99 103 110 118 124
46 51 60 67 73 81 87 94 103 109
34 35 40 48 60 69 77 81 85 88
28 26 31 36 45 54 59 64 69 72
32 31 41 39 39 40 45 52 61 66
38 38 47 42 38 36 38 43 49 53
37 38 39 39 37 37 37 36 34 32
36 36 38 36 35 34 35 32 28 25

View File

@ -1,10 +0,0 @@
96 101 113 118 124 130 136 141 147 150
81 87 98 101 107 112 117 123 130 135
73 78 85 90 95 99 103 110 118 124
46 51 60 67 73 81 87 94 103 109
34 35 40 48 60 69 77 81 85 88
28 26 31 36 45 54 59 64 69 72
32 31 41 39 39 40 45 52 61 66
38 38 47 42 38 36 38 43 49 53
37 38 39 39 37 37 37 36 34 32
36 36 38 36 35 34 35 32 28 25
1 96 101 113 118 124 130 136 141 147 150
2 81 87 98 101 107 112 117 123 130 135
3 73 78 85 90 95 99 103 110 118 124
4 46 51 60 67 73 81 87 94 103 109
5 34 35 40 48 60 69 77 81 85 88
6 28 26 31 36 45 54 59 64 69 72
7 32 31 41 39 39 40 45 52 61 66
8 38 38 47 42 38 36 38 43 49 53
9 37 38 39 39 37 37 37 36 34 32
10 36 36 38 36 35 34 35 32 28 25

View File

@ -1,11 +0,0 @@
10 10
96 101 113 118 124 130 136 141 147 150
81 87 98 101 107 112 117 123 130 135
73 78 85 90 95 99 103 110 118 124
46 51 60 67 73 81 87 94 103 109
34 35 40 48 60 69 77 81 85 88
28 26 31 36 45 54 59 64 69 72
32 31 41 39 39 40 45 52 61 66
38 38 47 42 38 36 38 43 49 53
37 38 39 39 37 37 37 36 34 32
36 36 38 36 35 34 35 32 28 25

View File

@ -1,6 +0,0 @@
P5
#vips2ppm - Fri Aug 23 12:47:38 2019
10 10
255
`eqv|ˆ<E2809A>QWbekpu{‡INUZ_cgnv|.3<CIQW^gm"#(0<EMQUX$-6;@EH )''(-4=B&&/*&$&+15%&''%%%$" $$&$#"# 

View File

@ -1,6 +0,0 @@
P6
#vips2ppm - Fri Aug 23 12:47:50 2019
10 10
255
g[ilaoxm{{s€<73>yˆ<E280A0>Œ…—<E280A6>œ•<C593>¤˜”¥\K[`Rai]klaophwtm}yr„wŒ„•‰…TBRYHX^P_aUcf[kh_plcvrjzr‰€y:(6=-:E7DJ>LQDUWL]\SfcZolbzri|.(/)3#.9+8E7FM@QSHYVM`ZQf]Tg' %*$- *6(5=1?C6HG;OL@VOCW,!)!3$+2",0#-1#05(9</AE8LJ=Q1"%/#%7+/3&-/"+- */!04&7:+>>/B.""/##0$&/#'.!(.!*. --.+.)-," ,"!/##-!#,&+'-*+*'(#%

View File

@ -17,11 +17,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -19,11 +19,9 @@ test_one_file( const char *name )
NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -22,17 +22,15 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
struct mosaic_opt *opt;
double d;
if( size < sizeof(struct mosaic_opt) )
if( size < sizeof( struct mosaic_opt ) )
return( 0 );
if( !(ref = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( ref->Xsize > 1024 ||
ref->Ysize > 1024 ||
ref->Bands > 10 ) {
if( ref->Xsize > 100 ||
ref->Ysize > 100 ||
ref->Bands > 4 ) {
g_object_unref( ref );
return( 0 );
}
@ -44,10 +42,10 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
/* Extract some bytes from the tail to fuzz the arguments of the API.
*/
opt = (struct mosaic_opt *) (data + size - sizeof(struct mosaic_opt));
opt = (struct mosaic_opt *) (data + size - sizeof( struct mosaic_opt ));
if( vips_mosaic( ref, sec, &out, (VipsDirection) opt->dir,
opt->xref, opt->yref, opt->xsec, opt->ysec, NULL ) ) {
opt->xref, opt->yref, opt->xsec, opt->ysec, NULL ) ) {
g_object_unref( sec );
g_object_unref( ref );
return( 0 );

View File

@ -17,11 +17,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -16,11 +16,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -16,11 +16,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -3,7 +3,7 @@
#set -x
set -e
# Glib is build without -fno-omit-frame-pointer. We need
# Glib is built without -fno-omit-frame-pointer. We need
# to disable the fast unwinder to get full stacktraces.
export ASAN_OPTIONS="fast_unwind_on_malloc=0:allocator_may_return_null=1"
export UBSAN_OPTIONS="print_stacktrace=1"
@ -14,8 +14,12 @@ export VIPS_WARNING=0
ret=0
for fuzzer in *_fuzzer; do
find "common_fuzzer_corpus" -type f -not -empty -print0 \
| xargs -0 -n1 "./$fuzzer" || ret=1
for file in common_fuzzer_corpus/*; do
if ! ./$fuzzer $file; then
echo FAIL $fuzzer $file
ret=1
fi
done
done
exit $ret

View File

@ -16,11 +16,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -17,11 +17,9 @@ LLVMFuzzerTestOneInput( const guint8 *data, size_t size )
if( !(image = vips_image_new_from_buffer( data, size, "", NULL )) )
return( 0 );
/* Skip big images. They are likely to timeout.
*/
if( image->Xsize > 1024 ||
image->Ysize > 1024 ||
image->Bands > 10 ) {
if( image->Xsize > 100 ||
image->Ysize > 100 ||
image->Bands > 4 ) {
g_object_unref( image );
return( 0 );
}

View File

@ -1,6 +1,6 @@
OPTIONAL_COMPILE_DIR =
OPTIONAL_COMPILE_DIR =
OPTIONAL_DIST_DIR =
OPTIONAL_LIB =
OPTIONAL_LIB =
if ENABLE_DEPRECATED
OPTIONAL_COMPILE_DIR += deprecated
@ -24,8 +24,7 @@ SUBDIRS = \
iofuncs \
morphology \
mosaicing \
create
.
create
lib_LTLIBRARIES = libvips.la
@ -87,7 +86,7 @@ AM_LDFLAGS = \
LDADD = @INTROSPECTION_LIBS@ @VIPS_CFLAGS@ libvips.la @VIPS_LIBS@
noinst_PROGRAMS = \
introspect
introspect$(EXEEXT)
introspect_SOURCES = \
introspect.c
@ -96,7 +95,7 @@ introspect_SOURCES = \
introspection_sources = @vips_introspection_sources@
# we make the vips8 API
Vips-8.0.gir: introspect
Vips-8.0.gir: introspect$(EXEEXT)
Vips_8_0_gir_INCLUDES = GObject-2.0
Vips_8_0_gir_CFLAGS = $(INCLUDES) -I${top_srcdir}/libvips/include
Vips_8_0_gir_LIBS = libvips.la

View File

@ -261,7 +261,7 @@ vips_add_init( VipsAdd *add )
* range of possible values.
*
* Operations on integer images are performed using the processor's vector unit,
* if possible. Disable this with --vips-novector or IM_NOVECTOR.
* if possible. Disable this with --vips-novector or VIPS_NOVECTOR.
*
* See also: vips_subtract(), vips_linear().
*

View File

@ -562,7 +562,7 @@ vips_boolean_const_init( VipsBooleanConst *boolean_const )
static int
vips_boolean_constv( VipsImage *in, VipsImage **out,
VipsOperationBoolean operation, double *c, int n, va_list ap )
VipsOperationBoolean operation, const double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -609,7 +609,7 @@ vips_boolean_constv( VipsImage *in, VipsImage **out,
*/
int
vips_boolean_const( VipsImage *in, VipsImage **out,
VipsOperationBoolean boolean, double *c, int n, ... )
VipsOperationBoolean boolean, const double *c, int n, ... )
{
va_list ap;
int result;
@ -637,7 +637,8 @@ vips_boolean_const( VipsImage *in, VipsImage **out,
* Returns: 0 on success, -1 on error
*/
int
vips_andimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_andimage_const( VipsImage *in, VipsImage **out,
const double *c, int n, ... )
{
va_list ap;
int result;
@ -666,7 +667,8 @@ vips_andimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_orimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_orimage_const( VipsImage *in, VipsImage **out,
const double *c, int n, ... )
{
va_list ap;
int result;
@ -695,7 +697,8 @@ vips_orimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_eorimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_eorimage_const( VipsImage *in, VipsImage **out,
const double *c, int n, ... )
{
va_list ap;
int result;
@ -724,7 +727,7 @@ vips_eorimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_lshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_lshift_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -753,7 +756,7 @@ vips_lshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_rshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_rshift_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;

View File

@ -150,11 +150,12 @@ vips_hough_circle_vote_endpoints_clip( VipsImage *image,
int y, int x1, int x2, int quadrant, void *client )
{
int r = *((int *) client);
guint *line = (guint *) VIPS_IMAGE_ADDR( image, 0, y ) + r;
int b = image->Bands;
if( y >= 0 &&
y < image->Ysize ) {
guint *line = (guint *) VIPS_IMAGE_ADDR( image, 0, y ) + r;
if( x1 >=0 &&
x1 < image->Xsize )
line[x1 * b] += 1;
@ -278,6 +279,9 @@ vips_hough_circle_init( VipsHoughCircle *hough_circle )
* votes by circle circumference so circles of differing size are given equal
* weight.
*
* The output pixel at (x, y, band) is the strength of the circle centred on
* (x, y) and with radius (band).
*
* Use @max_radius and @min_radius to set the range of radii to search for.
*
* Use @scale to set how @in coordinates are scaled to @out coordinates. A

View File

@ -453,7 +453,7 @@ vips_linear_init( VipsLinear *linear )
static int
vips_linearv( VipsImage *in, VipsImage **out,
double *a, double *b, int n, va_list ap )
const double *a, const double *b, int n, va_list ap )
{
VipsArea *area_a;
VipsArea *area_b;
@ -500,7 +500,8 @@ vips_linearv( VipsImage *in, VipsImage **out,
* Returns: 0 on success, -1 on error
*/
int
vips_linear( VipsImage *in, VipsImage **out, double *a, double *b, int n, ... )
vips_linear( VipsImage *in, VipsImage **out,
const double *a, const double *b, int n, ... )
{
va_list ap;
int result;

View File

@ -420,7 +420,7 @@ vips_math2_const_init( VipsMath2Const *math2_const )
static int
vips_math2_constv( VipsImage *in, VipsImage **out,
VipsOperationMath2 math2, double *c, int n, va_list ap )
VipsOperationMath2 math2, const double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -470,7 +470,7 @@ vips_math2_constv( VipsImage *in, VipsImage **out,
*/
int
vips_math2_const( VipsImage *in, VipsImage **out,
VipsOperationMath2 math2, double *c, int n, ... )
VipsOperationMath2 math2, const double *c, int n, ... )
{
va_list ap;
int result;
@ -496,7 +496,7 @@ vips_math2_const( VipsImage *in, VipsImage **out,
* Returns: 0 on success, -1 on error
*/
int
vips_pow_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_pow_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -523,7 +523,7 @@ vips_pow_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_wop_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_wop_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;

View File

@ -598,7 +598,7 @@ vips_relational_const_init( VipsRelationalConst *relational_const )
static int
vips_relational_constv( VipsImage *in, VipsImage **out,
VipsOperationRelational relational, double *c, int n, va_list ap )
VipsOperationRelational relational, const double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -645,7 +645,7 @@ vips_relational_constv( VipsImage *in, VipsImage **out,
*/
int
vips_relational_const( VipsImage *in, VipsImage **out,
VipsOperationRelational relational, double *c, int n, ... )
VipsOperationRelational relational, const double *c, int n, ... )
{
va_list ap;
int result;
@ -671,7 +671,7 @@ vips_relational_const( VipsImage *in, VipsImage **out,
* Returns: 0 on success, -1 on error
*/
int
vips_equal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_equal_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -698,7 +698,8 @@ vips_equal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_notequal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_notequal_const( VipsImage *in, VipsImage **out,
const double *c, int n, ... )
{
va_list ap;
int result;
@ -725,7 +726,7 @@ vips_notequal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_less_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_less_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -752,7 +753,7 @@ vips_less_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_lesseq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_lesseq_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -779,7 +780,7 @@ vips_lesseq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_more_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_more_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;
@ -806,7 +807,7 @@ vips_more_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* Returns: 0 on success, -1 on error
*/
int
vips_moreeq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_moreeq_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
{
va_list ap;
int result;

View File

@ -333,7 +333,7 @@ vips_remainder_const_init( VipsRemainderConst *remainder_const )
static int
vips_remainder_constv( VipsImage *in, VipsImage **out,
double *c, int n, va_list ap )
const double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -379,7 +379,8 @@ vips_remainder_constv( VipsImage *in, VipsImage **out,
* Returns: 0 on success, -1 on error
*/
int
vips_remainder_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
vips_remainder_const( VipsImage *in, VipsImage **out,
const double *c, int n, ... )
{
va_list ap;
int result;

View File

@ -44,6 +44,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>

View File

@ -1,5 +1,7 @@
noinst_LTLIBRARIES = libcolour.la
SUBDIRS = profiles
libcolour_la_SOURCES = \
profiles.c \
profiles.h \
@ -42,7 +44,6 @@ profiles.c:
./wrap-profiles.sh profiles profiles.c
EXTRA_DIST = \
profiles \
wrap-profiles.sh
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -493,9 +493,7 @@ static VipsColourRoute vips_colour_routes[] = {
* vips_colourspace_issupported:
* @image: input image
*
* Test if @image is in a colourspace that vips_colourspace() can process. For
* example, #VIPS_INTERPRETATION_RGB images are not in a well-defined
* colourspace, but #VIPS_INTERPRETATION_sRGB ones are.
* Test if @image is in a colourspace that vips_colourspace() can process.
*
* Returns: %TRUE if @image is in a supported colourspace.
*/

View File

@ -282,7 +282,7 @@ vips_icc_build( VipsObject *object )
case cmsSigRgbData:
colour->interpretation =
icc->depth == 8 ?
VIPS_INTERPRETATION_RGB :
VIPS_INTERPRETATION_sRGB :
VIPS_INTERPRETATION_RGB16;
colour->format =
icc->depth == 8 ?

View File

@ -89,17 +89,14 @@ vips_profile_load_build( VipsObject *object )
build( object ) )
return( -1 );
if( g_ascii_strcasecmp( load->name, "none" ) == 0 ) {
if( g_ascii_strcasecmp( load->name, "none" ) == 0 )
profile = NULL;
}
else if( (data = vips_profile_fallback_get( load->name, &length )) ) {
else if( (data = vips_profile_fallback_get( load->name, &length )) )
profile = vips_blob_new( NULL, data, length );
}
else if( (data = vips__file_read_name( load->name,
vips__icc_dir(), &length )) ) {
vips__icc_dir(), &length )) )
profile = vips_blob_new(
(VipsCallbackFn) g_free, data, length );
}
else {
vips_error( class->nickname,
_( "unable to load profile \"%s\"" ), load->name );

View File

@ -0,0 +1,3 @@
EXTRA_DIST = \
cmyk.icm \
sRGB.icm

View File

@ -6,6 +6,9 @@
* - test and remove orientation from every ifd
* 6/10/18
* - don't remove orientation if it's one of the cases we don't handle
* 10/5/20
* - handle mirrored images
* - deprecate vips_autorot_get_angle()
*/
/*
@ -54,6 +57,7 @@ typedef struct _VipsAutorot {
VipsImage *in;
VipsAngle angle;
gboolean flip;
} VipsAutorot;
@ -61,83 +65,6 @@ typedef VipsConversionClass VipsAutorotClass;
G_DEFINE_TYPE( VipsAutorot, vips_autorot, VIPS_TYPE_CONVERSION );
/**
* vips_autorot_get_angle:
* @image: image to fetch orientation from
*
* Examine the metadata on @im and return the #VipsAngle to rotate by to turn
* the image upright.
*
* See also: vips_autorot().
*
* Returns: the #VipsAngle to rotate by to make the image upright.
*/
VipsAngle
vips_autorot_get_angle( VipsImage *im )
{
int orientation;
VipsAngle angle;
if( !vips_image_get_typeof( im, VIPS_META_ORIENTATION ) ||
vips_image_get_int( im, VIPS_META_ORIENTATION, &orientation ) )
orientation = 1;
switch( orientation ) {
case 6:
angle = VIPS_ANGLE_D90;
break;
case 8:
angle = VIPS_ANGLE_D270;
break;
case 3:
angle = VIPS_ANGLE_D180;
break;
default:
/* Other values do rotate + mirror, don't bother handling them
* though, how common can mirroring be.
*
* See:
*
* http://www.80sidea.com/archives/2316
*/
angle = VIPS_ANGLE_D0;
break;
}
return( angle );
}
/* TRUE if this is one of the cases we handle.
*/
static gboolean
vips_autorot_handled( VipsImage *im )
{
int orientation;
gboolean handled;
if( !vips_image_get_typeof( im, VIPS_META_ORIENTATION ) ||
vips_image_get_int( im, VIPS_META_ORIENTATION, &orientation ) )
orientation = 1;
switch( orientation ) {
case 1:
case 3:
case 6:
case 8:
handled = TRUE;
break;
default:
handled = FALSE;
break;
}
return( handled );
}
static void *
vips_autorot_remove_angle_sub( VipsImage *image,
const char *field, GValue *value, void *my_data )
@ -158,14 +85,14 @@ vips_autorot_remove_angle_sub( VipsImage *image,
* vips_autorot_remove_angle: (method)
* @image: image to remove orientation from
*
* Remove the orientation tag on @image. Also remove any exif orientation tags.
*
* See also: vips_autorot_get_angle().
* Remove the orientation tag on @image. Also remove any exif orientation tags.
* You must vips_copy() the image before calling this function since it
* modifies metadata.
*/
void
vips_autorot_remove_angle( VipsImage *image )
{
(void) vips_image_remove( image, VIPS_META_ORIENTATION );
(void) vips_image_remove( image, VIPS_META_ORIENTATION );
(void) vips_image_map( image, vips_autorot_remove_angle_sub, NULL );
}
@ -174,26 +101,87 @@ vips_autorot_build( VipsObject *object )
{
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsAutorot *autorot = (VipsAutorot *) object;
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 );
if( VIPS_OBJECT_CLASS( vips_autorot_parent_class )->build( object ) )
return( -1 );
VipsAngle angle;
gboolean flip;
VipsImage *in;
g_object_set( object,
"angle", vips_autorot_get_angle( autorot->in ),
NULL );
in = autorot->in;
switch( vips_image_get_orientation( in ) ) {
case 2:
angle = VIPS_ANGLE_D0;
flip = TRUE;
break;
case 3:
angle = VIPS_ANGLE_D180;
flip = FALSE;
break;
case 4:
angle = VIPS_ANGLE_D180;
flip = TRUE;
break;
case 5:
angle = VIPS_ANGLE_D90;
flip = TRUE;
break;
case 6:
angle = VIPS_ANGLE_D90;
flip = FALSE;
break;
case 7:
angle = VIPS_ANGLE_D270;
flip = TRUE;
break;
case 8:
angle = VIPS_ANGLE_D270;
flip = FALSE;
break;
case 1:
default:
angle = VIPS_ANGLE_D0;
flip = FALSE;
break;
if( vips_autorot_handled( autorot->in ) ) {
if( vips_rot( autorot->in, &t[0], autorot->angle, NULL ) )
return( -1 );
vips_autorot_remove_angle( t[0] );
}
else {
if( vips_copy( autorot->in, &t[0], NULL ) )
return( -1 );
}
if( vips_image_write( t[0], conversion->out ) )
g_object_set( object,
"angle", angle,
"flip", flip,
NULL );
if( angle != VIPS_ANGLE_D0 ) {
if( vips_rot( in, &t[0], angle, NULL ) )
return( -1 );
in = t[0];
}
if( flip ) {
if( vips_flip( in, &t[1], VIPS_DIRECTION_HORIZONTAL, NULL ) )
return( -1 );
in = t[1];
}
/* We must copy before modifying metadata.
*/
if( vips_copy( in, &t[2], NULL ) )
return( -1 );
in = t[2];
vips_autorot_remove_angle( in );
if( vips_image_write( in, conversion->out ) )
return( -1 );
return( 0 );
@ -223,13 +211,21 @@ vips_autorot_class_init( VipsAutorotClass *class )
_( "Angle image was rotated by" ),
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsAutorot, angle ),
VIPS_TYPE_ANGLE, VIPS_ANGLE_D0 );
VIPS_TYPE_ANGLE, VIPS_ANGLE_D0 );
VIPS_ARG_BOOL( class, "flip", 7,
_( "Flip" ),
_( "Whether the image was flipped or not" ),
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsAutorot, flip ),
FALSE );
}
static void
vips_autorot_init( VipsAutorot *autorot )
{
autorot->angle = VIPS_ANGLE_D0;
autorot->flip = FALSE;
}
/**
@ -241,18 +237,14 @@ vips_autorot_init( VipsAutorot *autorot )
* Optional arguments:
*
* * @angle: output #VipsAngle the image was rotated by
* * @flip: output %gboolean whether the image was flipped
*
* Look at the image metadata and rotate the image to make it upright. The
* #VIPS_META_ORIENTATION tag is removed from @out to prevent accidental
* double rotation.
* Look at the image metadata and rotate and flip the image to make it
* upright. The #VIPS_META_ORIENTATION tag is removed from @out to prevent
* accidental double rotation.
*
* Read @angle to find the amount the image was rotated by.
*
* vips only supports the four simple rotations, it does not support the
* various mirror modes. If the image is using one of these mirror modes, the
* image is not rotated and the #VIPS_META_ORIENTATION tag is not removed.
*
* See also: vips_autorot_get_angle(), vips_autorot_remove_angle(), vips_rot().
* Read @angle to find the amount the image was rotated by. Read @flip to
* see if the image was also flipped.
*
* Returns: 0 on success, -1 on error
*/
@ -268,4 +260,3 @@ vips_autorot( VipsImage *in, VipsImage **out, ... )
return( result );
}

View File

@ -126,10 +126,11 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
#define CAST_SHORT( X ) VIPS_CLIP( SHRT_MIN, (X), SHRT_MAX )
/* We know the source cannot be the same as the dest, so we will only use
* CAST_UINT() for an INT source, and vice versa.
* CAST_UINT() for an INT source, and vice versa. We don't need to clip to
* INT_MAX, since float->int does that for us.
*/
#define CAST_UINT( X ) VIPS_MAX( 0, (X) )
#define CAST_INT( X ) VIPS_MIN( (X), INT_MAX )
#define CAST_INT( X ) (X)
/* Rightshift an integer type, ie. sizeof(ITYPE) > sizeof(OTYPE).
*/

View File

@ -343,6 +343,13 @@ vips_composite_base_max_band( VipsCompositeBase *composite, double *max_band )
max_band[2] = 255;
break;
case VIPS_INTERPRETATION_CMYK:
max_band[0] = 255;
max_band[1] = 255;
max_band[2] = 255;
max_band[3] = 255;
break;
case VIPS_INTERPRETATION_RGB16:
max_band[0] = 65535;
max_band[1] = 65535;
@ -621,7 +628,7 @@ vips_composite_base_blend( VipsCompositeBase *composite,
case VIPS_BLEND_MODE_DIFFERENCE:
for( int b = 0; b < bands; b++ )
f[b] = abs( B[b] - A[b] );
f[b] = fabs( B[b] - A[b] );
break;
case VIPS_BLEND_MODE_EXCLUSION:

View File

@ -214,6 +214,7 @@
* @VIPS_INTERESTING_ATTENTION: look for features likely to draw human attention
* @VIPS_INTERESTING_LOW: position the crop towards the low coordinate
* @VIPS_INTERESTING_HIGH: position the crop towards the high coordinate
* @VIPS_INTERESTING_ALL: everything is interesting
*
* Pick the algorithm vips uses to decide image "interestingness". This is used
* by vips_smartcrop(), for example, to decide what parts of the image to

View File

@ -195,6 +195,11 @@ vips_sequential_build( VipsObject *object )
if( vips_linecache( sequential->in, &t,
"tile_height", sequential->tile_height,
"access", VIPS_ACCESS_SEQUENTIAL,
/* We need seq caches to persist across minimise in case
* someone is trying to read an image with a series of crop
* operations.
*/
"persistent", TRUE,
NULL ) )
return( -1 );

View File

@ -12,6 +12,8 @@
* - move shrink to start of processing
* 22/9/18 jcupitt
* - add low and high
* 19/3/20 jcupitt
* - add all
*/
/*
@ -345,8 +347,8 @@ vips_smartcrop_build( VipsObject *object )
break;
case VIPS_INTERESTING_CENTRE:
left = (smartcrop->in->Xsize - smartcrop->width) / 2;
top = (smartcrop->in->Ysize - smartcrop->height) / 2;
left = (in->Xsize - smartcrop->width) / 2;
top = (in->Ysize - smartcrop->height) / 2;
break;
case VIPS_INTERESTING_ENTROPY:
@ -360,8 +362,15 @@ vips_smartcrop_build( VipsObject *object )
break;
case VIPS_INTERESTING_HIGH:
left = smartcrop->in->Xsize - smartcrop->width;
top = smartcrop->in->Ysize - smartcrop->height;
left = in->Xsize - smartcrop->width;
top = in->Ysize - smartcrop->height;
break;
case VIPS_INTERESTING_ALL:
left = 0;
top = 0;
smartcrop->width = in->Xsize;
smartcrop->height = in->Ysize;
break;
default:
@ -448,10 +457,10 @@ vips_smartcrop_init( VipsSmartcrop *smartcrop )
* Crop an image down to a specified width and height by removing boring parts.
*
* Use @interesting to pick the method vips uses to decide which bits of the
* image should be kept.
* image should be kept.
*
* You can test xoffset / yoffset on @out to find the location of the crop
* within the input image.
* within the input image.
*
* See also: vips_extract_area().
*

View File

@ -74,8 +74,8 @@ vips_switch_gen( VipsRegion *or, void *seq, void *a, void *b,
if( vips_reorder_prepare_many( or->im, ar, r ) )
return( -1 );
g_assert( ar->im->BandFmt == VIPS_FORMAT_UCHAR );
g_assert( ar->im->Bands == 1 );
g_assert( ar[0]->im->BandFmt == VIPS_FORMAT_UCHAR );
g_assert( ar[0]->im->Bands == 1 );
for( i = 0; i < swit->n; i++ ) {
p[i] = VIPS_REGION_ADDR( ar[i], r->left, r->top );

View File

@ -35,8 +35,6 @@
* - terminate on tile calc error
* 7/3/17
* - remove "access" on linecache, use the base class instead
* 15/2/19
* - remove the search for LRU, have a gqueue instead, much faster
*/
/*
@ -127,10 +125,6 @@ typedef struct _VipsBlockCache {
int tile_height;
int max_tiles;
/* access doesn't actually have any effect now. It used to set
* the order for the recycle queue, but there's no efficient way to do
* top-most, so we're just always LRU.
*/
VipsAccess access;
gboolean threaded;
gboolean persistent;
@ -254,6 +248,30 @@ vips_tile_search( VipsBlockCache *cache, int x, int y )
return( tile );
}
static void
vips_tile_find_is_topper( gpointer element, gpointer user_data )
{
VipsTile *this = (VipsTile *) element;
VipsTile **best = (VipsTile **) user_data;
if( !*best ||
this->pos.top < (*best)->pos.top )
*best = this;
}
/* Search the recycle list for the topmost tile.
*/
static VipsTile *
vips_tile_find_topmost( GQueue *recycle )
{
VipsTile *tile;
tile = NULL;
g_queue_foreach( recycle, vips_tile_find_is_topper, &tile );
return( tile );
}
/* Find existing tile, make a new tile, or if we have a full set of tiles,
* reuse one.
*/
@ -282,12 +300,18 @@ vips_tile_find( VipsBlockCache *cache, int x, int y )
return( tile );
}
/* Reuse an old one, if there are any.
/* Reuse an old one, if there are any. We just peek the tile pointer,
* it is removed from the recycle list later on _ref.
*/
if( cache->recycle )
/* Gets removed from the recycle list on _ref.
*/
tile = g_queue_peek_head( cache->recycle );
if( cache->recycle ) {
if( cache->access == VIPS_ACCESS_RANDOM )
tile = g_queue_peek_head( cache->recycle );
else
/* This is slower :( We have to search the recycle
* queue.
*/
tile = vips_tile_find_topmost( cache->recycle );
}
if( !tile ) {
/* There are no tiles we can reuse -- we have to make another
@ -913,8 +937,7 @@ vips_line_cache_build( VipsObject *object )
block_cache->tile_width = block_cache->in->Xsize;
/* Output has two buffers n_lines height, so 2 * n_lines is the maximum
* non-locality from threading. Add another n_lines for conv / reducev
* etc.
* non-locality from threading. Double again for conv, rounding, etc.
*
* tile_height can be huge for things like tiff read, where we can
* have a whole strip in a single tile ... we still need to have a
@ -922,7 +945,7 @@ vips_line_cache_build( VipsObject *object )
* tile boundary.
*/
block_cache->max_tiles = VIPS_MAX( 2,
3 * n_lines / block_cache->tile_height );
4 * n_lines / block_cache->tile_height );
VIPS_DEBUG_MSG( "vips_line_cache_build: n_lines = %d\n",
n_lines );

View File

@ -62,6 +62,7 @@ typedef struct _VipsUnpremultiply {
VipsImage *in;
double max_alpha;
int alpha_band;
} VipsUnpremultiply;
@ -76,17 +77,21 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
OUT * restrict q = (OUT *) out; \
\
for( x = 0; x < width; x++ ) { \
IN alpha = p[bands - 1]; \
IN clip_alpha = VIPS_CLIP( 0, alpha, max_alpha ); \
OUT nalpha = (OUT) clip_alpha / max_alpha; \
IN alpha = p[alpha_band]; \
\
if( nalpha == 0 ) \
for( i = 0; i < bands - 1; i++ ) \
q[i] = 0; \
if( alpha != 0 ) { \
OUT factor = max_alpha / alpha; \
\
for( i = 0; i < alpha_band; i++ ) \
q[i] = factor * p[i]; \
q[alpha_band] = alpha; \
} \
else \
for( i = 0; i < bands - 1; i++ ) \
q[i] = p[i] / nalpha; \
q[i] = clip_alpha; \
for( i = 0; i < alpha_band + 1; i++ ) \
q[i] = 0; \
\
for( i = alpha_band + 1; i < bands; i++ ) \
q[i] = p[i]; \
\
p += bands; \
q += bands; \
@ -101,20 +106,21 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
\
for( x = 0; x < width; x++ ) { \
IN alpha = p[3]; \
IN clip_alpha = VIPS_CLIP( 0, alpha, max_alpha ); \
OUT nalpha = (OUT) clip_alpha / max_alpha; \
\
if( nalpha == 0 ) { \
if( alpha != 0 ) { \
OUT factor = max_alpha / alpha; \
\
q[0] = factor * p[0]; \
q[1] = factor * p[1]; \
q[2] = factor * p[2]; \
q[3] = alpha; \
} \
else { \
q[0] = 0; \
q[1] = 0; \
q[2] = 0; \
q[3] = 0; \
} \
else { \
q[0] = p[0] / nalpha; \
q[1] = p[1] / nalpha; \
q[2] = p[2] / nalpha; \
} \
q[3] = clip_alpha; \
\
p += 4; \
q += 4; \
@ -141,6 +147,7 @@ vips_unpremultiply_gen( VipsRegion *or, void *vseq, void *a, void *b,
int width = r->width;
int bands = im->Bands;
double max_alpha = unpremultiply->max_alpha;
int alpha_band = unpremultiply->alpha_band;
int x, y, i;
@ -235,6 +242,11 @@ vips_unpremultiply_build( VipsObject *object )
in->Type == VIPS_INTERPRETATION_RGB16 )
unpremultiply->max_alpha = 65535;
/* Is alpha-band unset? Default to the final band for this image.
*/
if( !vips_object_argument_isset( object, "alpha_band" ) )
unpremultiply->alpha_band = in->Bands - 1;
if( in->BandFmt == VIPS_FORMAT_DOUBLE )
conversion->out->BandFmt = VIPS_FORMAT_DOUBLE;
else
@ -279,6 +291,13 @@ vips_unpremultiply_class_init( VipsUnpremultiplyClass *class )
G_STRUCT_OFFSET( VipsUnpremultiply, max_alpha ),
0, 100000000, 255 );
VIPS_ARG_INT( class, "alpha_band", 116,
_( "Alpha band" ),
_( "Unpremultiply with this alpha" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsUnpremultiply, alpha_band ),
0, 100000000, 3 );
}
static void
@ -296,10 +315,11 @@ vips_unpremultiply_init( VipsUnpremultiply *unpremultiply )
* Optional arguments:
*
* * @max_alpha: %gdouble, maximum value for alpha
* * @alpha_band: %gint, band containing alpha data
*
* Unpremultiplies any alpha channel.
* The final band is taken to be the alpha
* and the bands are transformed as:
* Band @alpha_band (by default the final band) contains the alpha and all
* other bands are transformed as:
*
* |[
* alpha = (int) clip( 0, in[in.bands - 1], @max_alpha );
@ -312,8 +332,7 @@ vips_unpremultiply_init( VipsUnpremultiply *unpremultiply )
*
* So for an N-band image, the first N - 1 bands are divided by the clipped
* and normalised final band, the final band is clipped.
* If there is only a single band,
* the image is passed through unaltered.
* If there is only a single band, the image is passed through unaltered.
*
* The result is
* #VIPS_FORMAT_FLOAT unless the input format is #VIPS_FORMAT_DOUBLE, in which

View File

@ -34,11 +34,6 @@
*/
/* This is a simple wrapper over the old vips7 functions. At some point we
* should rewrite this as a pure vips8 class and redo the vips7 functions as
* wrappers over this.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/

View File

@ -147,9 +147,6 @@ typedef struct {
typedef struct {
VipsConvolution parent_instance;
/* An int version of M.
*/
VipsImage *iM;
int n_point; /* w * h for our matrix */
/* We make a smaller version of the mask with the zeros squeezed out.
@ -853,7 +850,6 @@ vips__image_intize( VipsImage *in, VipsImage **out )
static int
vips_convi_intize( VipsConvi *convi, VipsImage *M )
{
int n_point;
VipsImage *t;
double scale;
double *scaled;
@ -862,21 +858,17 @@ vips_convi_intize( VipsConvi *convi, VipsImage *M )
int shift;
int i;
n_point = M->Xsize * M->Ysize;
g_assert( convi->n_point == n_point );
if( vips_check_matrix( "vips2imask", M, &t ) )
return( -1 );
/* Bake the scale into the mask to make a double version.
*/
scale = vips_image_get_scale( t );
if( !(scaled = VIPS_ARRAY( convi, n_point, double )) ) {
if( !(scaled = VIPS_ARRAY( convi, convi->n_point, double )) ) {
g_object_unref( t );
return( -1 );
}
for( i = 0; i < n_point; i++ )
for( i = 0; i < convi->n_point; i++ )
scaled[i] = VIPS_MATRIX( t, 0, 0 )[i] / scale;
g_object_unref( t );
@ -896,7 +888,7 @@ vips_convi_intize( VipsConvi *convi, VipsImage *M )
mx = scaled[0];
mn = scaled[0];
for( i = 1; i < n_point; i++ ) {
for( i = 1; i < convi->n_point; i++ ) {
if( scaled[i] > mx )
mx = scaled[i];
if( scaled[i] < mn )
@ -915,7 +907,7 @@ vips_convi_intize( VipsConvi *convi, VipsImage *M )
/* We need to sum n_points, so we have to shift right before adding a
* new value to make sure we have enough range.
*/
convi->sexp = ceil( log2( n_point ) );
convi->sexp = ceil( log2( convi->n_point ) );
if( convi->sexp > 10 ) {
g_info( "vips_convi_intize: mask too large" );
return( -1 );
@ -925,9 +917,9 @@ vips_convi_intize( VipsConvi *convi, VipsImage *M )
*/
convi->exp = 7 - shift - convi->sexp;
if( !(convi->mant = VIPS_ARRAY( convi, n_point, int )) )
if( !(convi->mant = VIPS_ARRAY( convi, convi->n_point, int )) )
return( -1 );
for( i = 0; i < n_point; i++ ) {
for( i = 0; i < convi->n_point; i++ ) {
/* 128 since this is signed.
*/
convi->mant[i] = VIPS_RINT( 128 * scaled[i] * pow(2, -shift) );
@ -965,7 +957,7 @@ vips_convi_intize( VipsConvi *convi, VipsImage *M )
true_sum = 0.0;
int_sum = 0;
for( i = 0; i < n_point; i++ ) {
for( i = 0; i < convi->n_point; i++ ) {
int value;
true_sum += 128 * scaled[i];
@ -1001,7 +993,6 @@ vips_convi_build( VipsObject *object )
VipsImage *in;
VipsImage *M;
int n_point;
VipsGenerateFn generate;
double *coeff;
int i;
@ -1047,19 +1038,18 @@ vips_convi_build( VipsObject *object )
*/
if( vips__image_intize( M, &t[1] ) )
return( -1 );
convi->iM = M = t[1];
M = t[1];
coeff = VIPS_MATRIX( M, 0, 0 );
n_point = M->Xsize * M->Ysize;
if( !(convi->coeff = VIPS_ARRAY( object, n_point, int )) ||
if( !(convi->coeff = VIPS_ARRAY( object, convi->n_point, int )) ||
!(convi->coeff_pos =
VIPS_ARRAY( object, n_point, int )) )
VIPS_ARRAY( object, convi->n_point, int )) )
return( -1 );
/* Squeeze out zero mask elements.
*/
convi->nnz = 0;
for( i = 0; i < n_point; i++ )
for( i = 0; i < convi->n_point; i++ )
if( coeff[i] ) {
convi->coeff[convi->nnz] = coeff[i];
convi->coeff_pos[convi->nnz] = i;

View File

@ -157,19 +157,19 @@ vips_convolution_init( VipsConvolution *convolution )
void
vips_convolution_operation_init( void )
{
extern int vips_conv_get_type( void );
extern int vips_conva_get_type( void );
extern int vips_convf_get_type( void );
extern int vips_convi_get_type( void );
extern int vips_convsep_get_type( void );
extern int vips_convasep_get_type( void );
extern int vips_compass_get_type( void );
extern int vips_fastcor_get_type( void );
extern int vips_spcor_get_type( void );
extern int vips_sharpen_get_type( void );
extern int vips_gaussblur_get_type( void );
extern int vips_sobel_get_type( void );
extern int vips_canny_get_type( void );
extern GType vips_conv_get_type( void );
extern GType vips_conva_get_type( void );
extern GType vips_convf_get_type( void );
extern GType vips_convi_get_type( void );
extern GType vips_convsep_get_type( void );
extern GType vips_convasep_get_type( void );
extern GType vips_compass_get_type( void );
extern GType vips_fastcor_get_type( void );
extern GType vips_spcor_get_type( void );
extern GType vips_sharpen_get_type( void );
extern GType vips_gaussblur_get_type( void );
extern GType vips_sobel_get_type( void );
extern GType vips_canny_get_type( void );
vips_conv_get_type();
vips_conva_get_type();

View File

@ -64,7 +64,7 @@ vips_convsep_build( VipsObject *object )
VipsConvolution *convolution = (VipsConvolution *) object;
VipsConvsep *convsep = (VipsConvsep *) object;
VipsImage **t = (VipsImage **)
vips_object_local_array( object, 3 );
vips_object_local_array( object, 4 );
VipsImage *in;
@ -86,19 +86,19 @@ vips_convsep_build( VipsObject *object )
in = t[0];
}
else {
if( vips_rot( convolution->M, &t[0], VIPS_ANGLE_D90, NULL ) )
return( -1 );
/* We must only add the offset once.
/* Take a copy, since we must set the offset.
*/
vips_image_set_double( t[0], "offset", 0 );
if( vips_rot( convolution->M, &t[0], VIPS_ANGLE_D90, NULL ) ||
vips_copy( t[0], &t[3], NULL ) )
return( -1 );
vips_image_set_double( t[3], "offset", 0 );
if( vips_conv( in, &t[1], convolution->M,
"precision", convsep->precision,
"layers", convsep->layers,
"cluster", convsep->cluster,
NULL ) ||
vips_conv( t[1], &t[2], t[0],
vips_conv( t[1], &t[2], t[3],
"precision", convsep->precision,
"layers", convsep->layers,
"cluster", convsep->cluster,

View File

@ -64,9 +64,12 @@ vips_mask_butterworth_point( VipsMask *mask, double dx, double dy )
double cnst = (1.0 / ac) - 1.0;
double fc2 = fc * fc;
double dist2 = fc2 / (dx * dx + dy * dy);
double d = dx * dx + dy * dy;
return( 1.0 / (1.0 + cnst * pow( dist2, order )) );
if( d == 0 )
return( 0 );
else
return( 1.0 / (1.0 + cnst * pow( fc2 / d, order )) );
}
static void

View File

@ -30,6 +30,8 @@
* - set Xoffset/Yoffset to ink left/top
* 27/6/19
* - fitting could occasionally terminate early [levmorozov]
* 16/5/20 [keiviv]
* - don't add fontfiles repeatedly
*/
/*
@ -103,6 +105,10 @@ typedef VipsCreateClass VipsTextClass;
G_DEFINE_TYPE( VipsText, vips_text, VIPS_TYPE_CREATE );
/* ... single-thread the body of vips_text() with this.
*/
static GMutex *vips_text_lock = NULL;
/* Just have one of these and reuse it.
*
* This does not unref cleanly on many platforms, so we will leak horribly
@ -111,9 +117,10 @@ G_DEFINE_TYPE( VipsText, vips_text, VIPS_TYPE_CREATE );
*/
static PangoFontMap *vips_text_fontmap = NULL;
/* ... single-thread the body of vips_text() with this.
/* All the fontfiles we've loaded. fontconfig lets you add a fontfile
* repeatedly, and we obviously don't want that.
*/
static GMutex *vips_text_lock = NULL;
static GHashTable *vips_text_fontfiles = NULL;
static void
vips_text_dispose( GObject *gobject )
@ -182,6 +189,7 @@ vips_text_get_extents( VipsText *text, VipsRect *extents )
pango_ft2_font_map_set_resolution(
PANGO_FT2_FONT_MAP( vips_text_fontmap ), text->dpi, text->dpi );
VIPS_UNREF( text->layout );
if( !(text->layout = text_layout_new( text->context,
text->text, text->font,
text->width, text->spacing, text->align, text->justify )) )
@ -239,6 +247,7 @@ vips_text_autofit( VipsText *text )
target.width = text->width;
target.height = text->height;
previous_dpi = -1;
previous_difference = 0;
#ifdef DEBUG
printf( "vips_text_autofit: "
@ -348,17 +357,26 @@ vips_text_build( VipsObject *object )
if( !vips_text_fontmap )
vips_text_fontmap = pango_ft2_font_map_new();
if( !vips_text_fontfiles )
vips_text_fontfiles =
g_hash_table_new( g_str_hash, g_str_equal );
text->context = pango_font_map_create_context(
PANGO_FONT_MAP( vips_text_fontmap ) );
if( text->fontfile &&
!FcConfigAppFontAddFile( NULL,
!g_hash_table_lookup( vips_text_fontfiles, text->fontfile ) ) {
if( !FcConfigAppFontAddFile( NULL,
(const FcChar8 *) text->fontfile ) ) {
vips_error( class->nickname,
_( "unable to load font \"%s\"" ), text->fontfile );
g_mutex_unlock( vips_text_lock );
return( -1 );
vips_error( class->nickname,
_( "unable to load font \"%s\"" ),
text->fontfile );
g_mutex_unlock( vips_text_lock );
return( -1 );
}
g_hash_table_insert( vips_text_fontfiles,
text->fontfile,
g_strdup( text->fontfile ) );
}
/* If our caller set height and not dpi, we adjust dpi until
@ -541,7 +559,7 @@ vips_text_init( VipsText *text )
* * @fontfile: %gchararray, load this font file
* * @width: %gint, image should be no wider than this many pixels
* * @height: %gint, image should be no higher than this many pixels
* * @align: #VipsAlign, left/centre/right alignment
* * @align: #VipsAlign, set justification alignment
* * @justify: %gboolean, justify lines
* * @dpi: %gint, render at this resolution
* * @autofit_dpi: %gint, read out auto-fitted DPI
@ -562,11 +580,12 @@ vips_text_init( VipsText *text )
*
* @width is the number of pixels to word-wrap at. Lines of text wider than
* this will be broken at word boundaries.
* @align can be used to set the alignment style for multi-line
* text. Note that the output image can be wider than @width if there are no
* word breaks, or narrower if the lines don't break exactly at @width.
*
* Set @justify to turn on line justification.
* @align can be used to set the alignment style for multi-line
* text to the low (left) edge centre, or high (right) edge. Note that the
* output image can be wider than @width if there are no
* word breaks, or narrower if the lines don't break exactly at @width.
*
* @height is the maximum number of pixels high the generated text can be. This
* only takes effect when @dpi is not set, and @width is set, making a box.

View File

@ -176,7 +176,7 @@ im_isvips( const char *filename )
{
unsigned char buf[4];
if( im__get_bytes( filename, buf, 4 ) ) {
if( im__get_bytes( filename, buf, 4 ) == 4 ) {
if( buf[0] == 0x08 && buf[1] == 0xf2 &&
buf[2] == 0xa6 && buf[3] == 0xb6 )
/* SPARC-order VIPS image.
@ -212,7 +212,7 @@ vips_flags( const char *filename )
flags = VIPS_FORMAT_PARTIAL;
if( im__get_bytes( filename, buf, 4 ) &&
if( im__get_bytes( filename, buf, 4 ) == 4 &&
buf[0] == 0x08 &&
buf[1] == 0xf2 &&
buf[2] == 0xa6 &&

View File

@ -61,6 +61,8 @@ im_csv2vips( const char *filename, IMAGE *out )
char mode[FILENAME_MAX];
char *p, *q, *r;
VipsImage *x;
/* Parse mode string.
*/
im_filename_split( filename, name, mode );
@ -76,9 +78,18 @@ im_csv2vips( const char *filename, IMAGE *out )
lines = atoi( r );
}
if( vips__csv_read( name, out,
start_skip, lines, whitespace, separator, FALSE ) )
if( vips_csvload( name, &x,
"skip", start_skip,
"lines", lines,
"whitespace", whitespace,
"separator", separator,
NULL ) )
return( -1 );
if( vips_image_write( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}

View File

@ -111,9 +111,18 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
}
#ifdef HAVE_JPEG
if( vips__jpeg_read_file( filename, out,
header_only, shrink, fail_on_warn, FALSE ) )
{
VipsSource *source;
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( vips__jpeg_read_source( source, out,
header_only, shrink, fail_on_warn, FALSE ) ) {
VIPS_UNREF( source );
return( -1 );
}
VIPS_UNREF( source );
}
#else
vips_error( "im_jpeg2vips",
"%s", _( "no JPEG support in your libvips" ) );

View File

@ -83,14 +83,21 @@ png2vips( const char *name, IMAGE *out, gboolean header_only )
}
#ifdef HAVE_PNG
if( header_only ) {
if( vips__png_header( filename, out ) )
return( -1 );
}
else {
if( vips__png_read( filename, out, TRUE ) )
return( -1 );
}
{
VipsSource *source;
int result;
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( header_only )
result = vips__png_header_source( source, out );
else
result = vips__png_read_source( source, out, TRUE );
VIPS_UNREF( source );
if( result )
return( result );
}
#else
vips_error( "im_png2vips",
"%s", _( "no PNG support in your libvips" ) );

View File

@ -52,6 +52,57 @@
#include "../foreign/pforeign.h"
#ifdef HAVE_TIFF
static gboolean
im_istifftiled( const char *filename )
{
VipsSource *source;
gboolean result;
if( !(source = vips_source_new_from_file( filename )) )
return( FALSE );
result = vips__istiff_source( source );
VIPS_UNREF( source );
return( result );
}
static int
im_tiff_read_header( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
VipsSource *source;
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( vips__tiff_read_header_source( source,
out, page, n, autorotate, -1 ) ) {
VIPS_UNREF( source );
return( -1 );
}
VIPS_UNREF( source );
return( 0 );
}
static int
im_tiff_read( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate )
{
VipsSource *source;
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( vips__tiff_read_source( source, out, page, n, autorotate, -1 ) ) {
VIPS_UNREF( source );
return( -1 );
}
VIPS_UNREF( source );
return( 0 );
}
#endif /*HAVE_TIFF*/
static int
tiff2vips( const char *name, IMAGE *out, gboolean header_only )
{
@ -88,18 +139,18 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only )
if( !header_only &&
!seq &&
!vips__istifftiled( filename ) &&
!im_istifftiled( filename ) &&
out->dtype == VIPS_IMAGE_PARTIAL ) {
if( vips__image_wio_output( out ) )
return( -1 );
}
if( header_only ) {
if( vips__tiff_read_header( filename, out, page, 1, FALSE ) )
if( im_tiff_read_header( filename, out, page, 1, FALSE ) )
return( -1 );
}
else {
if( vips__tiff_read( filename, out, page, 1, FALSE ) )
if( im_tiff_read( filename, out, page, 1, FALSE ) )
return( -1 );
}
#else

View File

@ -51,14 +51,21 @@ webp2vips( const char *name, IMAGE *out, gboolean header_only )
im_filename_split( name, filename, mode );
#ifdef HAVE_LIBWEBP
if( header_only ) {
if( vips__webp_read_file_header( filename, out, 0, 1, 1 ) )
return( -1 );
}
else {
if( vips__webp_read_file( filename, out, 0, 1, 1 ) )
return( -1 );
}
{
VipsSource *source;
int result;
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( header_only )
result = vips__webp_read_header_source( source, out, 0, 1, 1 );
else
result = vips__webp_read_source( source, out, 0, 1, 1 );
VIPS_UNREF( source );
if( result )
return( result );
}
#else
vips_error( "im_webp2vips",
"%s", _( "no webp support in your libvips" ) );
@ -69,6 +76,25 @@ webp2vips( const char *name, IMAGE *out, gboolean header_only )
return( 0 );
}
static gboolean
vips__iswebp( const char *filename )
{
gboolean result;
#ifdef HAVE_LIBWEBP
VipsSource *source;
if( !(source = vips_source_new_from_file( filename )) )
return( FALSE );
result = vips__iswebp_source( source );
VIPS_UNREF( source );
#else /*!HAVE_LIBWEBP*/
result = -1;
#endif /*HAVE_LIBWEBP*/
return( result );
}
int
im_webp2vips( const char *name, IMAGE *out )
{

View File

@ -123,7 +123,7 @@ lrmosaic_vec( im_object *argv )
int balancetype = *((int *) argv[10]);
int mwidth = *((int *) argv[11]);
return( im_lrmosaic( argv[0], argv[1], argv[2],
return( vips_lrmosaic( argv[0], argv[1], argv[2],
bandno,
xr, yr, xs, ys,
halfcorrelation, halfarea,
@ -210,7 +210,7 @@ find_lroverlap_vec( im_object *argv )
if( !(t = im_open( "find_lroverlap_vec", "p" )) )
return( -1 );
result = im__find_lroverlap( argv[0], argv[1], t,
result = vips__find_lroverlap( argv[0], argv[1], t,
bandno,
xr, yr, xs, ys,
halfcorrelation, halfarea,
@ -257,7 +257,7 @@ tbmosaic_vec( im_object *argv )
int balancetype = *((int *) argv[10]);
int mwidth = *((int *) argv[11]);
return( im_tbmosaic( argv[0], argv[1], argv[2],
return( vips_tbmosaic( argv[0], argv[1], argv[2],
bandno,
x1, y1, x2, y2,
halfcorrelation, halfarea,
@ -315,7 +315,7 @@ find_tboverlap_vec( im_object *argv )
if( !(t = im_open( "find_tboverlap_vec", "p" )) )
return( -1 );
result = im__find_tboverlap( argv[0], argv[1], t,
result = vips__find_tboverlap( argv[0], argv[1], t,
bandno,
xr, yr, xs, ys,
halfcorrelation, halfarea,
@ -367,7 +367,7 @@ lrmerge_vec( im_object *argv )
int dy = *((int *) argv[4]);
int mwidth = *((int *) argv[5]);
return( im_lrmerge( argv[0], argv[1], argv[2], dx, dy, mwidth ) );
return( vips_lrmerge( argv[0], argv[1], argv[2], dx, dy, mwidth ) );
}
/* Call im_lrmerge1 via arg vector.
@ -421,7 +421,7 @@ tbmerge_vec( im_object *argv )
int dy = *((int *) argv[4]);
int mwidth = *((int *) argv[5]);
return( im_tbmerge( argv[0], argv[1], argv[2], dx, dy, mwidth ) );
return( vips_tbmerge( argv[0], argv[1], argv[2], dx, dy, mwidth ) );
}
/* Call im_tbmerge1 via arg vector.
@ -594,7 +594,7 @@ correl_vec( im_object *argv )
int *y = (int *) argv[9];
double *correlation = (double *) argv[10];
return( im_correl( argv[0], argv[1],
return( vips_correl( argv[0], argv[1],
xref, yref, xsec, ysec, cor, area, correlation, x, y ) );
}

View File

@ -801,3 +801,15 @@ vips_warn( const char *domain, const char *fmt, ... )
va_end( ap );
}
/**
* vips_autorot_get_angle:
* @image: image to fetch orientation from
*
* This function is deprecated. Use vips_autorot() instead.
*/
VipsAngle
vips_autorot_get_angle( VipsImage *im )
{
return( VIPS_ANGLE_D0 );
}

View File

@ -4370,6 +4370,68 @@ im_profile( IMAGE *in, IMAGE *out, int dir )
return( 0 );
}
int
im_erode( IMAGE *in, IMAGE *out, INTMASK *mask )
{
VipsImage *t1, *t2;
if( !(t1 = vips_image_new()) ||
im_imask2vips( mask, t1 ) )
return( -1 );
if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_ERODE,
NULL ) ) {
g_object_unref( t1 );
return( -1 );
}
g_object_unref( t1 );
if( vips_image_write( t2, out ) ) {
g_object_unref( t2 );
return( -1 );
}
g_object_unref( t2 );
return( 0 );
}
int
im_erode_raw( IMAGE *in, IMAGE *out, INTMASK *m )
{
return( im_erode( in, out, m ) );
}
int
im_dilate( IMAGE *in, IMAGE *out, INTMASK *mask )
{
VipsImage *t1, *t2;
if( !(t1 = vips_image_new()) ||
im_imask2vips( mask, t1 ) )
return( -1 );
if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_DILATE,
NULL ) ) {
g_object_unref( t1 );
return( -1 );
}
g_object_unref( t1 );
if( vips_image_write( t2, out ) ) {
g_object_unref( t2 );
return( -1 );
}
g_object_unref( t2 );
return( 0 );
}
int
im_dilate_raw( IMAGE *in, IMAGE *out, INTMASK *m )
{
return( im_dilate( in, out, m ) );
}
int
im_mpercent( IMAGE *in, double percent, int *out )
{

View File

@ -69,7 +69,7 @@
* to be a slow way to do it. This is where the draw operations come in.
*
* To use these operations, use vips_copy() to make a copy of the image you
* want to modify, to ensure that no one else is using it, then call a
* want to modify to ensure that no one else is using it, then call a
* series of draw operations.
* Once you are done drawing, return to normal use of vips operations. Any time
* you want to start drawing again, you'll need to copy again.

Some files were not shown because too many files have changed in this diff Show More